zoukankan      html  css  js  c++  java
  • 51系列小型操作系统精髓 简单实现

    源代码地址(专业定制程序: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。 ;********************************************* ;------------------------------------------------------------- 演示样例程序 ;*********************************************** NAME RTOS_C ;程序段名 ?

    PR?RTOS?RTOS_C SEGMENT CODE ;代码段 ; 段名 SEGMENT 段类型 ?

    DT?RTOS?RTOS_C SEGMENT DATA ?

    ID?

    RTOS?

    RTOS_C SEGMENT IDATA PUBLIC RTOS PUBLIC _RTOS_WAIT PUBLIC _RTOS_INIT ;--------------------------------------------- ;BANBH EQU 0A3H ;版本 101221 ;定义数据地址 ;---------------------------------------------- RSEG ?

    DT?RTOS?RTOS_C ;RWZT EQU 29H ;任务状态,0为停止,1为正在运行 TL: DS 1 ;EQU 30H ;RTOS定时器值,C=FFFFH-ft TH: DS 1 ;EQU 31H ;18.432MHz(12周期)=C400H RWB: DS 1 ;EQU 33H ;任务表 RSEG ?

    ID?RTOS?RTOS_C RWDZ: DS 16 ;任务堆栈 ; EQU 80H ;任务地址 ; EQU 8FH RWS: DS 8 ;任务数 ; EQU 90H ;任务定时数 ; EQU 97H ;********************************************* 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: MOV A,R7 ;接收參数 MOV R5,A ;接收的数存在R5 MOV R7,#0 ;R7清零 CALL YXJSZ ;优先级设置 CJNE R7,#8,RWSZ ;R7假设不等 于8,则任务设置 MOV R7,#0FFH ;返回值0xff 当指定优先级被占用时自己主动向高优先级调整,在R7中返回实际优先级,当全部高优先级都被占用时返回 0FFH。任务将被忽略。

    RET ;返回 ;--------------------------------------------- RWSZ: MOV A,R7 ;送任务数 ADD A,#RWS ; MOV R0,A ;任务数保存到R0 MOV A,R5 ;R5上是什么 定时时间 MOV @R0,A ;保存定时时间数到【R7+RWS】位置 MOV A,R7 ;送 RL A ; ADD A,#RWDZ MOV R0,A POP ACC ;跳转地址,在堆栈中 POP B MOV @R0,B ;低地址在低字节 INC R0 MOV @R0,A MOV B,R7 ;设置任务列表 CLR A ; 当前正在运行的程序假设被中断,而且中断中使用了此任务位。则此次任务将会丢失。 INC B ;能够关中断来解决此问题。 SETB C RWSZ2: RLC A DJNZ B,RWSZ2 ORL RWB,A RET ;-------------------------- YXJSZ: MOV B,R7 ;0 ;优先级设置 INC B ;B++ 1 MOV A,RWB ;0 CLR C ;0 YXJ2: RRC A ;RRC是带进位的循环右移指令 DJNZ B,YXJ2 ;假设B不等于0。 b=0 YXJ4: JNC YXJ3 ;C=0 ,则 RRC A ; INC R7 ; JMP YXJ4 ; YXJ3: RET ;返回 ;------------------------------- 中断程序 把全部相关寄存器内容压入堆栈 任务调度完后 再弹出来 RTOS: MOV TH0,TH ;重载定时数 MOV TL0,TL ; JB PSW.3,RTOS1 ;RS0==1 用于选择当前工作寄存器区。8051有8个8位寄存器R0~R7 JB PSW.4,RTOS2 ;RS1==1 PUSH 0 ;RS0=0,RS1=0; 第一组寄存器区 PUSH 1 PUSH 2 PUSH 3 PUSH 4 PUSH 5 PUSH 6 PUSH 7 ;存入椎栈第一组寄存器上的内容 JMP RTOS0 ;都跳到RTOS0 RTOS1: JB PSW.4,RTOS3 ; PUSH 8 ;RS0=1,RS1=0; 第三组寄存器区 PUSH 9 PUSH 10 PUSH 11 PUSH 12 PUSH 13 PUSH 14 PUSH 15 JMP RTOS0 ; RTOS2: PUSH 10H ;RS0=0,RS1=1; 第二组寄存器区 PUSH 11H PUSH 12H PUSH 13H PUSH 14H PUSH 15H PUSH 16H PUSH 17H JMP RTOS0 RTOS3: PUSH 18H ;RS0=1,RS1=1; 第四组寄存器区 PUSH 19H PUSH 1AH PUSH 1BH PUSH 1CH PUSH 1DH PUSH 1EH PUSH 1FH RTOS0: PUSH PSW ;入栈 PUSH ACC ; PUSH B PUSH DPL PUSH DPH CALL RWDD0 ;任务调度 POP DPH ;出栈 POP DPL POP B POP ACC POP PSW JB PSW.3,RTOS01 JB PSW.4,RTOS02 POP 7 POP 6 POP 5 POP 4 POP 3 POP 2 POP 1 POP 0 ;弹出第一组寄存器区上的变量 RETI ;中断返回 RTOS01: JB PSW.4,RTOS3 POP 15 POP 14 POP 13 POP 12 POP 11 POP 10 POP 9 POP 8 RETI RTOS02: POP 17H POP 16H POP 15H POP 14H POP 13H POP 12H POP 11H POP 10H RETI RTOS03: POP 1FH POP 1EH POP 1DH POP 1CH POP 1BH POP 1AH POP 19H POP 18H RETI ;----------------------------- 中断任务调度 RWDD0: MOV B,#7 ;任务号 MOV R0,#RWS+7 ; MOV R1,#0FFH ;运行任务号 MOV A,RWB JNZ RWDD3 RET RWDD3: CLR C RLC A JNC RWDD6 CJNE @R0,#0,RWDD2 RWDD4: CJNE R1,#0FFH,RWDD6 MOV R1,B RWDD6: DEC R0 DEC B JNZ RWDD3 CJNE R1,#0FFH,RWCL RET RWDD2: DEC @R0 CJNE @R0,#0,RWDD6 JMP RWDD4 ;--------------------------------- RWDD: MOV R1,#7 MOV R0,#RWS+7 MOV A,RWB JNZ RWDD03 RET RWDD03: CLR C RLC A JNC RWDD06 CJNE @R0,#0,RWDD06 JMP RWCL RWDD06: DEC R0 DEC R1 JNZ RWDD03 RET ;-------------------------------------- RWCL: MOV DPTR,#RWDD ;任务处理? PUSH DPL PUSH DPH MOV A,R1 RL A ADD A,#RWDZ MOV R0,A MOV A,@R0 PUSH ACC ;低地址在低字节 INC R0 MOV ACC,@R0 PUSH ACC MOV A,#0FFH ;清除任务列表 当前正在运行的程序假设在下一个中断到来时还未运行完。 它的优先级将变为最低优先级, INC R1 ;能够添加一个运行标志 RWZT 来解决此问题。 CLR C RWCL22: RLC A DJNZ R1,RWCL22 ANL RWB,A RETI ;*********************************** 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 时也必须定义为2
    	task_load(task1, 0);//将task1 函数装入0 号槽
    	task_load(task2, 1);//将task2 函数装入1 号槽
    	os_start(0);
    }
    


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

查看全文
  • 相关阅读:
    java_oop_方法2
    POJ 3276 Face The Right Way(反转)
    POJ 3276 Face The Right Way(反转)
    POJ 2566 Bound Found(尺取法,前缀和)
    POJ 2566 Bound Found(尺取法,前缀和)
    POJ 3320 Jessica's Reading Problem(尺取法)
    POJ 3320 Jessica's Reading Problem(尺取法)
    POJ 3061 Subsequence(尺取法)
    POJ 3061 Subsequence(尺取法)
    HDU 1222 Wolf and Rabbit(欧几里得)
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10682831.html
  • Copyright © 2011-2022 走看看