|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2014-4-19 01:11:30
|
显示全部楼层
本帖最后由 rh.s 于 2014-4-19 01:17 编辑
没事干,再改了一下,用了函数指针实现任务的装载挂起,但资源消耗多了好多。
- #ifndef __OS_H__
- #define __OS_H__
- /*顶层任务数量,可按需增加,最大为255个*/
- #define MAXTASKS 3
- /*信号数量,可按需增加,最大为255个*/
- #define MAXSEM 1
- typedef struct
- {
- unsigned char time;
- unsigned char (*fun)(void);
- } task;//任务状态结构
- typedef struct
- {
- unsigned char sem;
- }semaphore;//信号结构
- /*声明任务状态数组*/
- extern volatile task tasks[MAXTASKS];
- #if MAXSEM
- extern semaphore SEM[MAXSEM];
- #define sem0 0/*定义信号0的名字,取有意义的名字*/
- #define sem1 1
- /*OS初始化设置,在主文件内所有任务前引用*/
- #define _OSInit volatile task tasks[MAXTASKS];semaphore SEM[MAXSEM];
- #else
- /*OS初始化设置,在主文件内所有任务前引用*/
- #define _OSInit volatile task tasks[MAXTASKS];
- #endif
- /*任务开始宏,在任务函数的变量声明后引用*/
- #define _SS static unsigned char _lc=0;switch(_lc){default:
- /*任务结束宏,在任务尾引用*/
- #define _EE ;}; _lc=0;return 255;
- /*任务中断宏,在任务开始宏和结束宏之间的任意位置引用*/
- #define WaitX(tickets) do{_lc=(__LINE__+((__LINE__%256)==0))%256;return tickets ;} while(0);case (__LINE__+((__LINE__%256)==0))%256:
- /*初始化顶层任务,实际上是给timers清零;初始化信号量。在main()内任务调度前引用*/
- #define InitTasks() {unsigned char i; for(i=MAXTASKS;i>0 ;i--) tasks[i-1].time=255;for(i=MAXSEM;i>0 ;i--) SEM[i-1].sem=0;}
- #define Loadtask(TaskName,TaskID,Time) tasks[TaskID].fun =TaskName;tasks[TaskID].time=Time;
- #define Runtasks() {while(1){unsigned char i;for(i=1;i<MAXTASKS;i++){if(tasks[i].time==0) tasks[i].time=(tasks[i].fun)();}}}
- #define RuntasksA() if(tasks[0].time==0){tasks[0].time=(tasks[0].fun)();}
- #define Stoptask(TaskID) Tasks[TaskID].time=255;
- /*调用子任务,在任务函数内引用,可以多层嵌套*/
- #define CallSub(SubTaskName) do{unsigned char currdt; _lc=(__LINE__+((__LINE__%256)==0))%256; return 0; case (__LINE__+((__LINE__%256)==0))%256: currdt=SubTaskName(); if(currdt!=255) return currdt;} while(0);
- /*
- CallSub(x)是基于循环的,并非一次姓调用。 不管子任务中间有多少断点,也会忠实执行。
- 之所以 在X();前面加了一个WaitX(0); 就是为了保存调用的位置。 下次可以继续运行x();
- 这样就实现了循环。 而if (timer[currid]!=255) return 则正是为了保证在子任务没执行完的时候,调用者继续等待。
- */
- /*计时,在定时器中断内引用*/
- #define UpdateTimers() {unsigned char i; for(i=MAXTASKS;i>0 ;i--) {if((tasks[i-1].time!=0)&&(tasks[i-1].time!=255)) tasks[i-1].time --;}}
-
- /*初始化信号量*/
- //#define InitSem(sem) sem=0;
- /*等待信号量,接收到信号后先把信号量置1,处理完成后必须引用一次EndWaitSem(semx),以便其它在等待相同信号的任务接收信号。*/
- #define WaitSem(semx) do{SEM[semx].sem=1; WaitX(0); if (SEM[semx].sem>0) return 1; else SEM[semx].sem=1;} while(0);
- #define EndWaitSem(semx) SendSem(semx)/*传递信号以便其它在等待相同信号的任务接收信号。*/
- /*等待信号量或定时器溢出,接收到信号后先把信号量置1,处理完成后必须引用一次EndWaitSem(semx),以便其它在等待相同信号的任务接收信号。*/
- /*tickets为定时器(超时时间),最大为0xFFFE,溢出后任务不再等待,继续往下执行*/
- #define WaitSemX(semx,tickets) {unsigned int xxxxxxxooooooo;xxxxxxxooooooo=tickets;do { SEM[semx].sem=1; WaitX(0); if(SEM[semx].sem>0 && xxxxxxxooooooo>0){ xxxxxxxooooooo--; return 1;}else if (SEM[semx].sem==0) SEM[semx].sem=1; } while(0);
- #define EndWaitSemX(semx) if(xxxxxxxooooooo>0)SendSem(semx)}/*如果是信号触发,则传递信号以便其它在等待相同信号的任务接收信号。*/
- /*发送信号量*/
- #define SendSem(semx) do {SEM[semx].sem=0;} while(0);
- #endif
复制代码
- #include <reg51.h>
- #include"os.h"
- /****小小调度器开始**********************************************/
- _OSInit
- /*****小小调度器结束*******************************************************/
- sbit LED1 = P2^1;
- sbit LED2 = P2^2;
- sbit LED0 = P2^5;
- unsigned char task0(){
- _SS
- while(1){
- //WaitX(50);
- WaitSemX(0,500);
- LED0=!LED0;
- EndWaitSemX(0);
- }
- _EE
- }
- unsigned char task1(){
- _SS
- while(1){
- WaitX(100);
- LED1=!LED1;
-
- }
- _EE
- }
- unsigned char task2(){
- _SS
- while(1){
- WaitX(200);
- LED2=!LED2;
- //SendSem(0);
- }
- _EE
- }
- void InitT0()
- {
- TMOD = 0x21;
- IE |= 0x82; // 12t
- TL0=0Xff;
- TH0=0XDB;
- TR0 = 1;
- }
- void INTT0(void) interrupt 1 using 1
- {
- TL0=0Xff; //10ms 重装
- TH0=0XDB;//b7;
- UpdateTimers();
- RuntasksA();//任务0具有精确按时获得执行的权限,要求:task0每次执行消耗时间<0.5个 ticket
- }
- void main()
- {
- InitT0();
- InitTasks(); //初始化任务,实际上是给timers清零
- Loadtask(task1,1,0);
- Loadtask(task2,2,0);
- Loadtask(task0,0,0);
- Runtasks();
- }
复制代码 |
|