单片机下最小多任务程序

任务函数的书写:  
void 函数名(void){//任务函数必须定义为无参数型 
while(1){//任务函数不得返回,必须为死循环
 //....这里写任务处理代码  
 task_switch();//每执行一段时间任务,就释放CPU一下,让别的任务有机会运行. 
 } 
 } 
 
 任务装载:  
 task_load(函数名,任务槽号)   
 装载函数的动作可发生在任意时候,但通常是在main()中.
 要注意的是,在本例中由于没考虑任务换出, 
 所以在执行os_start()前必须将所有任务槽装满.
 之后可以随意更换任务槽中的任务.
 
启动任务调度器: os_start(任务槽号)   调用该宏后,
将从参数指定的任务槽开始执行任务调度.
本例为每切换一次任务需额外开销个机器周期,用于迁移堆栈


#include <reg51.h>  
/*============================以下为任务管理器代码============================*/   
#define MAX_TASKS 3//任务槽个数.在本例中并未考虑任务换入换出,所以实际运行的任务有多少个,就定义多少个任务槽,不可多定义或少定义   
unsigned char idata task_sp[MAX_TASKS];   //任务的栈指针           
#define MAX_TASK_DEP 12 //最大栈深.最低不得少于个,保守值为.     
//预估方法:以为基数,每增加一层函数调用,加字节.如果其间可能发生中断,则还要再加上中断需要的栈深.       
//减小栈深的方法:1.尽量少嵌套子程序2.调子程序前关中断. 
unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP];//任务堆栈.   
unsigned char task_id;//当前活动任务号


//任务切换函数(任务调度器) 
void task_switch()
{  
task_sp[task_id] = SP;   
if(++task_id == MAX_TASKS)  
task_id = 0;   
SP = task_sp[task_id]; 



//任务装入函数.将指定的函数(参数)装入指定(参数)的任务槽中.如果该槽中原来就有任务,则原任务丢失,但
系统本身不会发生错误.  
void task_load(unsigned int fn, unsigned char tid)
{  
task_sp[tid] = task_stack[tid] + 1;  
task_stack[tid][0] = (unsigned int)fn & 0xff;  
task_stack[tid][1] = (unsigned int)fn >> 8; 
}   
//从指定的任务开始运行任务调度.调用该宏后,将永不返回.  
#define os_start(tid) {task_id = tid,SP = task_sp[tid];return;}


/*============================以下为测试代码============================*/   
 unsigned char stra[3], strb[3];//用于内存块复制测试的数组.      
 //测试任务:复制内存块.每复制一个字节释放CPU一次 
 void task1()
 {  //每复制一个字节释放CPU一次,控制循环的变量必须考虑覆盖  
static unsigned char i;//如果将这个变量前的static去掉,会发生什么事?  
i = 0;   
while(1){//任务必须为死循环,不得退出函数,否则系统会崩溃  
stra[i] = strb[i];  
if(++i == sizeof(stra))    
i = 0;    //变量i在这里跨越了task_switch(),因此它必须定义为静态(static),否则它将会被其它进程修改,因为在另一个进程里也会用到该变量所占用的地址.  
task_switch();//释放CPU一会儿,让其它进程有机会运行.如果去掉该行,则别的进程永远不会被调用到 

 }   //测试任务:复制内存块.每复制一个字节释放CPU一次. 
 void task2()
 {  //每复制一个字节释放CPU一次,控制循环的变量必须考虑覆盖  
static unsigned char i;//如果将这个变量前的static去掉,将会发生覆盖问题.task1()和task2()会被编译器分配到同一个内存地址上,当两个任务同时运行时,i的值就会被两个任务改来改去 
i = 0;   
while(1){//任务必须为死循环,不得退出函数,否则系统会崩溃  
stra[i] = strb[i];   if(++i == sizeof(stra))   
i = 0;    //变量i在这里跨越了task_switch(),因此它必须定义为静态(static),否则它将会被其它进程修改,因为在另一个进程里也会用到该变量所占用的地址.  
task_switch();//释放CPU一会儿,让其它进程有机会运行.如果去掉该行,则别的进程永远不会被调 用到 

 }   //测试任务:复制内存块.复制完所有字节后释放CPU一次. 
 void task3()
 {  //复制全部字节后才释放CPU,控制循环的变量不须考虑覆盖 
 unsigned char i;//这个变量前不需要加static,因为在它的作用域内并没有释放过CPU   
 while(1){//任务必须为死循环,不得退出函数,否则系统会崩溃   
i = sizeof(stra);   
do{  
stra[i-1] = strb[i-1];  
}while(--i);    //变量i在这里已完成它的使命,所以无需定义为静态.你甚至可以定义为寄存器型(regiter) 
task_switch();//释放CPU一会儿,让其它进程有机会运行.如果去掉该行,则别的进程永远不会被调用到 

 }   
 void main()
 {  //在这个示例里并没有考虑任务的换入换出,所以任务槽必须全部用完,否则系统会崩溃. 
//这里装载了三个任务,因此在定义MAX_TASKS时也必须定义为 
task_load(task1, 0);//将task1函数装入号槽 
task_load(task2, 1);//将task2函数装入号槽  
task_load(task3, 2);//将task3函数装入号槽   
os_start(0);//启动任务调度,并从号槽开始运行.参数改为,则首先运行号槽.   
//调用该宏后,程序流将永不再返回main(),也就是说,该语句行之后的所有语句都不被执行到.
 }    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值