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蓝牙等不限。)

查看全文
  • 相关阅读:
    SWOT分析模型
    如果度过迷茫,是多些挫折还是少一些好呢?
    Ext.Net动态构建树TreePanel使用详解
    Ext.Net动态加载菜单执行事件
    通过教练提升领导力了解行为教练在何时无法发挥作用
    Ext.Net\ExtJs弹出消息Alert、MessageBox、Confirm使用详解
    把领导力转化为结果结果导向型领导力
    自由职业,我的半年总结
    关于自由职业的一些想法(采访整理)
    Ext.net文本输入框:Ext.form.TextField属性汇总
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10682831.html
  • Copyright © 2011-2022 走看看