51系列小型操作系统精髓 简单实现

来源:互联网 发布:matlab中矩阵向量化 编辑:程序博客网 时间:2024/05/17 20:30

源码地址(专业定制程序:MCU,Windows,Android ,VC串口,Android蓝牙等不限。)

1.切换任务并记录位置,保证在时间到后能切换回来。(在任务中切换出去,在定时器中切换回来。)(时间片轮转)




;********************************************;RTOS用定时器0的多任务处理程序;项目增加方式使用。;程序不影响其它数据,目前程序的前后段不能进行参数传递 。 最多可以同时运行8个任务,;执行时使用定时器0,定时时间根据初始化时的参数确定,一般为10mS。;当指定优先级被占用时自动向高优先级调整,在R7中返回实际优先级,当所有高优先级都被占用时返回 0FFH,任务将被忽略。;占用24H个内存单元。;如果程序不可再入,需要设定 RWZT 的标志位。调用前先检查相应位。;如果定时数设置过大,会引起一直在中断中,不能执行外部程序。如果任务执行时间过长,会引起堆栈溢出。;18.432MHz,单时钟周期模式。不用任务单取反,输出频率 1.3MHz ,指令周期 384 nS 。速度是带系统的 100 倍。;8个任务,只对管脚取反,T0=FEF0H,输出 2.8K 频率,为最高频率。执行周期不受任务影响。18.432MHz,单时钟周期模式。;1个任务,只对管脚取反,T0=FFE1H,输出 12K 频率,为最高频率。执行周期受任务影响。每次调度时间为42US。;*********************************************;-------------------------------------------------------------示例程序;***********************************************NAMERTOS_C    ;程序段名?PR?RTOS?RTOS_CSEGMENTCODE    ;代码段 ; 段名 SEGMENT 段类型 ?DT?RTOS?RTOS_CSEGMENT DATA?ID?RTOS?RTOS_CSEGMENT IDATAPUBLICRTOSPUBLIC_RTOS_WAITPUBLIC_RTOS_INIT;---------------------------------------------;BANBHEQU0A3H;版本号 101221;定义数据地址;----------------------------------------------RSEG?DT?RTOS?RTOS_C;RWZTEQU29H;任务状态,0为停止,1为正在执行TL:DS 1;EQU30H;RTOS定时器值,C=FFFFH-ftTH:DS 1;EQU31H;18.432MHz(12周期)=C400HRWB:DS 1;EQU33H;任务表RSEG?ID?RTOS?RTOS_CRWDZ:DS 16        ;任务堆栈;EQU80H;任务地址;EQU8FHRWS:DS 8;任务数;EQU90H;任务定时数;EQU97H;*********************************************        CSEG  AT   0BH         ;TO入口        JMP     RTOS;*********************************************RSEG?PR?RTOS?RTOS_C_RTOS_INIT:;任务初始化;-------------------------------------------- 在 R6 R7 中,设置定时值;RTOS定时器值,C=FFFFH-ft,18.432MHz(12周期)=C400H,40MHz(12周期)=7DC9H;定时器0定时程序,18.432MHz,10MS,方式1  ORL    TMOD,#01H   ;定时10MS  ;定时器0初始化,设置TMOD          MOV    TL0,R7          MOV TL,R7     ;设置TL          MOV    TH0,R6          MOV TH,R6       ;设置TH          MOV RWB,#0     ;任务表清0          SETB   TR0        ;启动定时器          SETB   ET0     ;打开中断          SETB   EA     ;打开总中断          RET                ;等待中断;********************************************** 等待函数,优先级为最低 0 级,等待时间放入 R7 中;目前函数不能传递参数_RTOS_WAIT:MOVA,R7 ;接收参数MOVR5,A;接收的数存在R5MOVR7,#0;R7清零CALLYXJSZ;优先级设置CJNER7,#8,RWSZ;R7如果不等 于8,则任务设置MOVR7,#0FFH;返回值0xff  当指定优先级被占用时自动向高优先级调整,在R7中返回实际优先级,当所有高优先级都被占用时返回 0FFH,任务将被忽略。RET;返回;---------------------------------------------RWSZ:MOVA,R7;送任务数ADDA,#RWS;MOVR0,A;任务数保存到R0MOVA,R5;R5上是什么  定时时间MOV@R0,A   ;保存定时时间数到【R7+RWS】位置MOVA,R7;送RLA;ADDA,#RWDZMOVR0,APOPACC;跳转地址,在堆栈中POPBMOV@R0,B;低地址在低字节INCR0MOV@R0,AMOVB,R7;设置任务列表 CLRA; 当前正在执行的程序如果被中断,并且中断中使用了此任务位,则此次任务将会丢失。INCB;可以关中断来解决此问题。SETBCRWSZ2:RLCADJNZB,RWSZ2ORLRWB,ARET;--------------------------YXJSZ:MOVB,R7;0 ;优先级设置INCB;B++ 1MOVA,RWB;0CLRC;0YXJ2:RRCA;RRC是带进位的循环右移指令DJNZB,YXJ2 ;如果B不等于0,  b=0YXJ4:JNCYXJ3;C=0 ,则 RRCA;INCR7;JMPYXJ4    ;YXJ3:RET ;返回 ;------------------------------- 中断程序   把所有相关寄存器内容压入堆栈  任务调度完后 再弹出来RTOS:MOV    TH0,TH;重载定时数MOV    TL0,TL;JBPSW.3,RTOS1;RS0==1 用于选择当前工作寄存器区。8051有8个8位寄存器R0~R7JBPSW.4,RTOS2;RS1==1 PUSH0;RS0=0,RS1=0;  第一组寄存器区PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7;存入椎栈第一组寄存器上的内容JMPRTOS0;都跳到RTOS0RTOS1:JBPSW.4,RTOS3;PUSH8;RS0=1,RS1=0;  第三组寄存器区PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15JMPRTOS0;RTOS2:PUSH10H;RS0=0,RS1=1;  第二组寄存器区PUSH11HPUSH12HPUSH13HPUSH14HPUSH15HPUSH16HPUSH17HJMPRTOS0RTOS3:PUSH18H;RS0=1,RS1=1;第四组寄存器区PUSH19HPUSH1AHPUSH1BHPUSH1CHPUSH1DHPUSH1EHPUSH1FHRTOS0:PUSHPSW ;入栈PUSHACC;PUSHBPUSHDPLPUSHDPHCALLRWDD0;任务调度POPDPH;出栈POPDPLPOPBPOPACCPOPPSWJBPSW.3,RTOS01JBPSW.4,RTOS02POP7POP6POP5POP4POP3POP2POP1POP0;弹出第一组寄存器区上的变量RETI;中断返回RTOS01:JBPSW.4,RTOS3POP15POP14POP13POP12POP11POP10POP9POP8RETIRTOS02:POP17HPOP16HPOP15HPOP14HPOP13HPOP12HPOP11HPOP10HRETIRTOS03:POP1FHPOP1EHPOP1DHPOP1CHPOP1BHPOP1AHPOP19HPOP18HRETI;-----------------------------中断任务调度RWDD0:MOVB,#7;任务号MOVR0,#RWS+7;MOVR1,#0FFH;执行任务号MOVA,RWBJNZRWDD3RETRWDD3:CLRCRLCAJNCRWDD6CJNE@R0,#0,RWDD2RWDD4:CJNER1,#0FFH,RWDD6MOVR1,BRWDD6:DECR0DECBJNZRWDD3CJNER1,#0FFH,RWCLRETRWDD2:DEC@R0CJNE@R0,#0,RWDD6JMPRWDD4;---------------------------------RWDD:MOVR1,#7MOVR0,#RWS+7MOVA,RWBJNZRWDD03RETRWDD03:CLRCRLCAJNCRWDD06CJNE@R0,#0,RWDD06JMPRWCLRWDD06:DECR0DECR1JNZRWDD03RET;--------------------------------------RWCL:MOVDPTR,#RWDD   ;任务处理?PUSHDPLPUSHDPHMOVA,R1RLAADDA,#RWDZMOVR0,AMOVA,@R0PUSHACC;低地址在低字节INCR0MOVACC,@R0PUSHACCMOVA,#0FFH;清除任务列表  当前正在执行的程序如果在下一个中断到来时还未执行完, 它的优先级将变为最低优先级,INCR1;可以加入一个执行标志 RWZT 来解决此问题。CLRCRWCL22:RLCADJNZR1,RWCL22ANLRWB,ARETI;***********************************END

C语言版切换示例(网摘)

#include <REG52.H>#define MAX_TASKS 2 //任务槽个数.必须和实际任务数一至#define MAX_TASK_DEP 12 //最大栈深.最低不得少于2 个,保守值为12.unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP];//任务堆栈.unsigned char idata task_sp[MAX_TASKS];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];}//任务装入函数.将指定的函数(参数1)装入指定(参数2)的任务槽中.如果该槽中原来就有任//务,则原任务丢失,但系统本身不会发生错误.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;}/*============================以下为测试代码==========================*/void task1(){static unsigned char i;while(1){i++;task_switch();//编译后在这里打上断点}}void task2(){static unsigned char j;while(1){j+=2;task_switch();//编译后在这里打上断点}}void main(){//这里装载了两个任务,因此在定义MAX_TASKS 时也必须定义为2task_load(task1, 0);//将task1 函数装入0 号槽task_load(task2, 1);//将task2 函数装入1 号槽os_start(0);}


源码地址(专业定制程序MCU,Windows,Android ,VC串口,Android蓝牙等不限。)

1 0
原创粉丝点击