从前从前发布过一篇http://www.51hei.com/mcu/1616.html 这个是改善版,批改了几个小问题.
//阐明本源码来自网络(DIY超轻量级多使命操作体系一文)
//============================================================================
//51有用多使命源码,欢迎引证改善,有新改善功用请回发一份给我谢谢!(请发邮箱)
//改善为守时中止内切换使命
//使命内能够设守时刻片长短,经过改守时器0初置的办法完成
//置守时器0 TL0=0xFF;的办法能够让出CPU使用权
//七彩惊云改善,QQ540953860 13880880726 胥先生
//选用本源码请保存各改善人的联络信息,以便同享和完善,请将各改善前版别补白在代码后边以便了解开展
//过程和各种不同层次单片机下的灵敏引证。
//请对每一句代码进行补白谢谢!
//============================================================================
//============================================================================
//你的改善阐明写这儿
//============================================================================
#include
#define MAX_TASKS 2 //使命槽个数.有必要和实践使命数一至
#define MAX_TASK_DEP 12 //最大栈深.最低不得少于2个,保存值为12.
//依据程序嵌套层数调整该值巨细,一起要算一下会不会溢出,这儿的设置很重要。
//还有便是重入问题,局部变量在使命切换时有或许被别的的使命改写。
//#define MAX_TASK_DEP 24 //最大栈深.最低不得少于2个,24.
unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP];//使命仓库数组.
unsigned char task_id; //当时活动使命号
unsigned char idata task_sp[MAX_TASKS];//栈目标寄存数组
bit RWCH_BZ=0;//使命切换标志变量
/*
//使命切换函数(使命调度器)
void task_switch(){ //簿本程序能够用来让出CPU使用权
task_sp[task_id] = SP; //存当时使命SP的值
if(++task_id == MAX_TASKS) //使命号++并比较,到最大置0以便重复切换使命
task_id = 0;
SP = task_sp[task_id]; //读取下一使命SP值,
} */
//使命装入函数.将指定的函数(参数1)装入指定(参数2)的使命槽中.假如该槽华夏来就有使命,则原使命丢掉,但体系自身不会产生过错.
void task_load(unsigned int fn, unsigned char tid){
task_sp[tid] = task_stack[tid] + 1; //装入使命SP数据
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;}
//这儿其实便是以改写SP指针的办法,回来时不再回来调用簿本程序的当地,而回来被新设定的SP指针指向的使命1首地址处运转。
/*============================以下为测验代码============================*/
void task1(){ //使命1
static unsigned char i;
while(1){
i++;
}
}
void task2(){//使命2
static unsigned char j;
while(1){
j+=2;
TL0=0xFF;//用置TL0的办法来进行让守时中止动作然后进行使命切换,让出CPU使用权给下一使命的办法更好
}
}
void main(){
//这儿装载了两个使命,因此在界说MAX_TASKS时也有必要界说为2
//=============================================================
//单片机初始化
// mov tmod,#20h ;串口通讯设置 串口方法3 波特9600 晶振11.59适用
//TMOD=0x20;//守时器1方法2
TMOD=0x22;//守时器0方法2,守时器1方法2
// mov Tl1,#0fdh ;
TL1=0xfa;
// mov th1,#0fdh ; TEL:028-89951522 转载请勿删去,谢谢!
TH1=0xfa;
// mov pcon,#128d ;QQ:540953860
//PCON=128;
PCON=0x80;
// mov sp,#60h
//SP=0x60;
IP=16;//串口中止设为高优先级
// mov scon,#0e0h
SCON=0xf0;//为e0时制止接纳数据
//setb tr1
TR1=1;//敞开守时器1
TR0=1;//敞开守时器0
ET0=1;//开守时器0中止
TL0=0x50;//守时器0初值设定
TH0=0x50;//在中止中设置它可完成时刻片调整
// setb ea
//=============================================================
task_load(task1, 0);//将task1函数装入0号槽
task_load(task2, 1);//将task2函数装入1号槽
EA=1;//开中止
os_start(0); //进入使命1
}
ckzd() interrupt 4 using 1//串行中止进口
{
}
timer0zd() interrupt 1 using 2//守时器0中止进口
{
//clr tr1;封闭守时器
TR0=0;
//clr et1;封闭守时中止
ET0=0;
// task_switch();//切换使命
//===========================================
//切换使命
task_sp[task_id] = SP;
if(++task_id == MAX_TASKS)
{
task_id = 0;
RWCH_BZ=1;//当task_id==0时阐明一切任都切换了一次,置标志不再对栈进行调整。
}
SP = task_sp[task_id];