主页 > 开源代码  > 

51单片机基于时间片轮转的简单rtos

51单片机基于时间片轮转的简单rtos

早就想写写这个了,正好赶上有点时间,写了一下基于51单片机的时间片轮转调度系统,简单的rtos,呵呵。直接上代码。

//基于51单片机时间片轮转的简单rtos。 #include"reg52.h" sbit led1 = P2^7; sbit led2 = P2^0; sbit key = P1^0; #define MAX_TASKS 3 //定义任务个数.必须和实际任务数一至 #define PUSH_TIMES 3 //时间中断中push使用的次数用debug看进入时间中断时的次数。 #define MAX_TASK_DEP (PUSH_TIMES+4) //任务槽深度; //经过实验,看debug的push次数,加上4就行了。//没有考虑中断嵌套。有嵌套的再大。 unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP]; //任务堆栈. unsigned char current_id; //当前活动任务号 unsigned char task_sp[MAX_TASKS]; //堆栈指针组,每个任务一个字节,任务调度前指向入栈的pc高字节。 unsigned int cicle1,cicle2; void Timer0_Init(void) //10毫秒@11.0592MHz { AUXR &= 0x7F; //定时器时钟12T模式 TMOD &= 0xF0; //设置定时器模式 TL0 = 0x00; //设置定时初始值 TH0 = 0xDC; //设置定时初始值 TF0 = 0; //清除TF0标志 ET0 = 1; //使能定时器0中断 EA=1; //开总中断 } //任务装入函数,将任务的首地址(参数1)装入(参数2)指定的任务槽中. void task_load(unsigned int func, unsigned char taskid) { task_stack[taskid][0] = (unsigned int)func & 0xff; //把任务地址的低八位装入任务槽0号地址。 task_stack[taskid][1] = (unsigned int)func >> 8; //把任务地址的高八位装入任务槽1号地址 task_sp[taskid] = (unsigned char)&task_stack[taskid][0]; //把堆栈的首地址送给sp数组。 task_sp[taskid]++;//先把保存的数组sp值加1,使它指向堆栈入栈pc的高位 //这里模拟了入栈过程,先把任务地址放在任务槽的最低位置,下次切换的时候就直接来这里找。 if(taskid!=0) //如果不是0号任务; { task_sp[taskid]+= PUSH_TIMES; //给push和pop语句留下空间,用debuge看汇编进入中断后的push //次数,在文件首部改数字值; } } void os_start() //启动程序 { current_id = 0; //把0号sp当作当前的首个sp SP = task_sp[0]; } void task1() //任务1,循环够5万次灯闪动一次 { while(1) { cicle1++; if (cicle1>50000) { cicle1=0; led1=!led1; } } } void task2() //任务2,循环够5万次灯闪动一次 { while(1) { cicle2++; if (cicle2>30000) { cicle2=0; led2=!led2; } } } void task3() { while(1) { if(key==0) cicle2=10000; // cicle1=10000; } } void Timer0_Isr(void) interrupt 1 //时间中断。调度任务。 { EA=0; //进入核心临界区关中断 task_sp[current_id] = SP; //将进入时钟中断时的sp存入任务槽。 if(++current_id == MAX_TASKS) //当前任务指向下一个任务号。如果任务号超过任务总数 current_id=0; //指向任务0; SP = task_sp[current_id]; //把新任务的pc地址给sp,这样在时间中断出函数的时候系统自动把sp指向的值作为pc高8位;并出栈。 EA=1; //开中断。 } void main() { //这里装载了三个个任务,因此在文件首部定义MAX_TASKS时也必须定义为3 task_load(task1, 0);//将task1函数装入0号槽,任务可以装入任意槽。 task_load(task2, 1);//将task2函数装入1号槽 task_load(task3, 2);//将task3函数装入2号槽 Timer0_Init(); //定时器0初始化 key=1; //口线置位。 TR0 = 1; //开始计时 os_start(); //必须从任务在0号槽的任务开始; }

虽然简单,也可以继续学习了。

标签:

51单片机基于时间片轮转的简单rtos由讯客互联开源代码栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“51单片机基于时间片轮转的简单rtos