学习之前需要安装keil
参照Keil uvision5安装
#include<stc8h.h>
#include<intrins.h>
#define MAX_TASKS 2 //假设当前系统只有2个task
#define MAX_TASK_DEP 32unsigned char idata task_sp[MAX_TASKS]; //任务的堆栈指针
unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP];//每个task任务的堆栈
unsigned char task_id;//当前任务号,从0开始
//当前任务状态
typedef enum{TASK_RUNNING,//运行状态TASK_SUSPENED //挂起状态
}TaskStatus;typedef struct{unsigned char id;//任务idTaskStatus status;//任务状态unsigned int delay_count;//延迟计数器unsigned int delay_duration;//延迟时间
}Task;Task idata tasks[MAX_TASKS]={{0,TASK_RUNNING,0,0},//两个任务都是默认运行状态,不延迟{0,TASK_RUNNING,0,0},};void Timer0_init(void);
void sleep(unsigned int,unsigned int);//tid delay_msvoid sleep(unsigned int tid,unsigned int delay_ms)
{tasks[task_id].status=TASK_SUSPENED;tasks[task_id].delay_count=0;tasks[task_id].delay_duration=delay_ms;
}void Timer0_init()
{AUXR |= 0x80; //定时器时钟1T模式TMOD &= 0xF0; //设置定时器模式TL0 = 0x40; //设置定时初始值TH0 = 0xA2; //设置定时初始值TF0 = 0; //清除TF0标志TR0 = 1; //定时器0开始计时}void Delay1000ms() //@24.000MHz
{unsigned char i, j, k;_nop_();_nop_();i = 122;j = 193;k = 128;do{do{while (--k);} while (--j);} while (--i);
}//定义一个任务切换的函数(任务调度器)
void task_switch(){task_sp[task_id]=SP;task_id=task_id+1;if(task_id==MAX_TASKS)task_id=0;SP=task_sp[task_id];}void task0(){//第0号任务//static unsigned int a=3;//避免两个变量分配到相同的寄存器P5M0=0x00;P5M1=0x00;P53=1;while(1) {//a=a+3;//检查自己的状态,如果自己是睡眠,就应该交给其他任务去执行if(tasks[0].status==TASK_SUSPENED){task_switch();continue;}//Delay1000ms();sleep(0,1000);P53=~P53;task_switch();}
}void task1(){//第1号任务//static unsigned int b=5;P4M1=0x00;P4M0=0x00;P2M0=0x00;P2M1=0x00;P27=0;while(1) {//b=b+5;//检查自己的状态,如果自己是睡眠,就应该交给其他任务去执行if(tasks[1].status==TASK_SUSPENED){task_switch();continue;}//Delay1000ms();sleep(1,1000);P27=~P27;task_switch();}
}void Timer0_ISR(void) interrupt 1{//系统的定时器中断,每隔1毫秒执行一次中断函数unsigned char i;for(i=0;i<MAX_TASKS;i++){if(tasks[i].status==TASK_SUSPENED) tasks[i].delay_count++;if(tasks[i].delay_count>=tasks[i].delay_duration) tasks[i].delay_count=0;//睡眠结束}
}void Timer1_init()
{AUXR |= 0x40; //定时器时钟1T模式TMOD &= 0x0F; //设置定时器模式TL0 = 0xA0; //设置定时初始值TH0 = 0xF6; //设置定时初始值TF0 = 0; //清除TF0标志TR0 = 1; //定时器0开始计时}void Timer1_ISR(void) interrupt 3{task_switch();//在timer1中的中断,自动进行任务切换
}//加载任务的函数,把一个task的函数指针放入对应的堆栈空间里面
//fn是一个函数指针,数据类型是int 16位的
//tid task_id 是8位的0,1
void task_load(unsigned int fn,unsigned char tid){task_sp[tid]=task_stack[tid]+1; //加载一个任务进入栈task_stack[tid][0]=fn& 0xff;//取低8位task_stack[tid][1]=fn>> 8 ;//取高8位}void main(){Timer0_init();Timer1_init();task_load(task0,0);//把task0装到内存里task_load(task1,1);//把task1装到内存里task_id=0;SP=task_sp[0];}