找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6772|回复: 0
收起左侧

51单片机汇编版的多任务实时操作系统

[复制链接]
ID:70941 发表于 2015-3-21 05:04 | 显示全部楼层 |阅读模式
51多任务实时操作系统—汇编:
   哈哈!今天发现用单片机处理多任务事件(多任务同时进行)的方法了!用单片机定时器中断进行任务的调度,定时的时间就是每项任务的一次可执行时间,每中断一次就切换一个任务,调度方法是定时器中断时保存上一任务的断点(出栈保存),跳到下一个任务(地址入栈,中断返回)。每个任务都必须是一个死循环,因为它是独立的!当然单片机不可能真正做到多任务同时进行,这个方法只是把各个任务拼接起来每个任务分配一定的时间!因为单片机的速度快,所以在一定意义上说这些任务是同时进行的!单片机的速度越快越好!这个方法的缺陷是软件延时很难计算,误差大.

    一个CPU是不可能同时处理多条指令的,只能是一条一条的顺序执行。如果我们需要同时执行多个任务,但又不能等一个任务执行完了再执行下一个任务,有的任务还需要等待一个信号触发才能往下执行,信号迟迟未来那就什么也做不了了!!操作系统的出现,就是为了解决这一问题的。它的功能就是能让CPU“同时”处理多个任务,当然不是真正的同时,它只是把这些任务的分成不同的时间段来处理,每个任务只执行很短的的时间(只执行一部分指令),然后保存断点就切换到下一个任务的指令去执行,同样只执行很短的的时间(只执行一部分指令),再保存断点切换任务。等所有的任务都执行一次后再回来从断点处继续执行,时间到,再保存断点切换任务,如此反复。因为CPU的频率高,所以完成一次循环的时间极短,51单片机的频率一般40MHz以内,所需时间是ms、us级的,电脑的主频是GHz级别的,那更不用说,这样短的时间对于我们来说就是同时的。

    学过C51的大都知道RTX51,它是单片机实时多任务系统,是kill51自带的,但是还有很多汇编爱好者不能使用它,因为它是C语言的。为此本人设计了两个个简单的汇编语言版的多任务实时系统,专为汇编爱好者提供一个参考。高手勿喷!
    本程序使用定时器中断的方法产生时间轮片,每个任务分配在一个时间轮片上。如果一个时间轮片(定时器的时间)是250us,那每个任务执行一次的时间就是250us(因为任务切换的时间极短,所以里省略了);有4个任务要执行,那么系统完成一次循环的时间是250*4=1000us=1ms。即先执行任务一250us,然后保存任务一的断点,切换到任务二执行250us,再保存任务二的断点,切换到任务三执行250us,接着保存任务三的断点,切换到任务四执行250us,保存任务四的断点,再次切到任务一断点处继续往下执行250us,再保存再切换到下一个任务的断点处执行,照此循环。所以这些任务并不是同1us内完成的,而是同1ms内完成的,当然更是同时同分同秒完成的。
程序只是个演示程序,功能的开发看个人要求而定!
轻量四任务实时系统

ORG 0000H
RW1_SP  DATA  20H;任务堆栈指针位置寄存器
RW2_SP  DATA  21H
RW3_SP  DATA  22H
RW4_SP  DATA  23H

ORG 0000H
AJMP MAIN
ORG 000BH
LJMP RWQHCX
ORG0076H   
;================任务切换程序===========================================

RWQHCX:
JNB   RS0,LOOP3
JNB   RS1,LOOP4
;==============任务4现场保护
PUSH  ACC        ;需注意与任务4现场还原对应
PUSH  B
PUSH  PSW
MOV   RW4_SP,SP  ;保存任务4的堆栈指针位置
;==============任务1现场还原
MOV   SP,RW1_SP  ;取任务1的堆栈指针位置,任务1使用寄存器0组
POP  PSW          ;需注意与任务1现场保护对应
POP  B
POP  ACC
RETI
LOOP2:
;==============任务1现场保护
PUSH  ACC        ;需注意与任务1现场还原对应
PUSH  B
PUSH  PSW
MOV   RW1_SP,SP  ;保存任务1的堆栈指针位置
;==============任务2现场还原
MOV   SP,RW2_SP  ;取任务2的堆栈指针位置,任务2使用寄存器1组
POP  PSW          ;需注意与任务2现场保护对应
POP  B
POP  ACC
RETI
LOOP3:
JNB   RS1,LOOP2
;==============任务2现场保护
PUSH  ACC        ;需注意与任务2现场还原对应
PUSH  B
PUSH  PSW
MOV   RW2_SP,SP  ;保存任务2的堆栈指针位置
;==============任务3现场还原
MOV   SP,RW3_SP  ;取任务3的堆栈指针位置,任务3使用寄存器2组
POP  PSW           ;需注意与任务3现场保护对应
POP  B
POP  ACC
RETI
LOOP4:
;==============任务3现场保护
PUSH  ACC        ;需注意与任务3现场还原对应
PUSH  B
PUSH  PSW
MOV   RW3_SP,SP  ;保存任务4的堆栈指针位置
;==============任务4现场还原
MOV  SP,RW4_SP  ;取任务4的堆栈指针位置,任务4使用寄存器3组
POP  PSW         ;需注意与任务4现场保护对应
POP  B
POP  ACC
RETI


;========任务一程序===============================
RW1_KS:             ;任务一入口(初始化)
CLR   RS0
CLR   RS1
;你的初始化程序
;========任务一程序===============================
RW1_MAIN:           ;任务一主程序
;你的程序
LJMP  RW1_MAIN
============任务一END===================================

;========任务二程序===============================
RW2_KS:             ;任务二入口(初始化)
CLR   RS0
SETB  RS1
;你的初始化程序
RW2_MAIN:           ;任务二主程序
;你的程序
LJMP  RW2_MAIN
============任务二END===================================


;========任务三程序===============================
RW3_KS:             ;任务三入口(初始化)
SETB  RS0
CLR   RS1
;你的初始化程序
RW3_MAIN:           ;任务三主程序
;你的程序
LJMP  RW3_MAIN
============任务三END===================================

;========任务四程序===============================
RW4_KS:             ;任务四入口(初始化)
SETB  RS0
SETB  RS1
;你的初始化程序
RW4_MAIN:           ;任务四主程序
;你的程序
LJMP  RW4_MAIN
============任务四END===================================


===============初始化程序==================================

MAIN:
MOV   SP,#09FH;取任务2堆栈指针开始位置
MOV   DPTR,#RW2_KS
PUSH  DPL
PUSH  DPH
MOV   RW2_SP,#0A4H;任务2堆栈指针寄存器初值=09FH+2+任务2现场保护入栈数
MOV   SP,#0BFH;取任务3堆栈指针开始位置
MOV   DPTR,#RW3_KS
PUSH  DPL
PUSH  DPH
MOV   RW3_SP,#0C4H;任务3堆栈指针寄存器初值=0BFH+2+任务3现场保护入栈数
MOV   SP,#0DFH;取任务4堆栈指针开始位置
MOV   DPTR,#RW4_KS
PUSH  DPL
PUSH  DPH
MOV   RW4_SP,#0E4H;任务4堆栈指针寄存器初值=0DFH+2+任务4现场保护入栈数

MOV   SP,#7FH;取任务1堆栈指针开始位置
SETB  EA    ;开启维持个任务调度的定时器
SETB  ET0
MOV   TMOD,#02H
SETB  TR0

LJMP   RW1_KS

END

要求不严谨的20任务系统

此程序结构很空洞,使用请自己注意



ORG 0000H
RWJSQ    data 7FH
RWJSQ1   data 7EH

ORG 0000H
AJMP MAIN
ORG 000BH
LJMP RWDD
ORG 0076H     
RWDD:         ;任务调度程序
MOV  R0,RWJSQ ;取任务地址寄存器地址
POP  ACC   
MOV  @R0,A   ;保存当前任务断点
INC  R0
POP  ACC
MOV  @R0,A
INC  R0
MOV  A,R0
CJNEA,RWJSQ1,LOOP2;所有需要进行的任务是否进行完
MOV  R0,#216     ;任务地址寄存器起始地址
LOOP2:
INC  R0
MOV  A,@R0   ;取另一个任务断点
PUSH ACC
DEC  R0
MOV  A,@R0
PUSH ACC
MOV  RWJSQ,R0 ;保存任务地址寄存器地址
CJNER0,#220,XXX  ;220是任务三的地址寄存器地址
INC  R4      ;延时基数
XXX:
RETI          ;前去执行新任务
MAIN:
MOV RWJSQ,#216 ;任务地址寄存器起始地址(最多20个任务,需40个寄存器)
MOV RWJSQ1,#0;任务地址寄存器地址的最后一个地址加一(取值218-0)
MOVR0,RWJSQ   ;取各个任务的地址
MOV DPTR,#RW1
LCALL DZSZ
MOV DPTR,#RW2
LCALL DZSZ
MOV DPTR,#RW3
LCALL DZSZ
MOV DPTR,#RW4
LCALL DZSZ
MOV DPTR,#RW5
LCALL DZSZ
MOV DPTR,#RW6
LCALL DZSZ
MOV DPTR,#RW7
LCALL DZSZ
MOV DPTR,#RW8
LCALL DZSZ
MOV DPTR,#RW9
LCALL DZSZ
MOV DPTR,#RW10
LCALL DZSZ
MOV DPTR,#RW11
LCALL DZSZ
MOV DPTR,#RW12
LCALL DZSZ
MOV DPTR,#RW13
LCALL DZSZ
MOV DPTR,#RW14
LCALL DZSZ
MOV DPTR,#RW15
LCALL DZSZ
MOV DPTR,#RW16
LCALL DZSZ
MOV DPTR,#RW17
LCALL DZSZ
MOV DPTR,#RW18
LCALL DZSZ
MOV DPTR,#RW19
LCALL DZSZ
MOV DPTR,#RW20
LCALL DZSZ
SETB  EA    ;开启维持个任务调度的定时器
SETB  ET0
MOV   TMOD,#02H ;
MOV   TH0,#6;定时器初值设置
SETB  TR0
LJMP  RW1   ;跳到第一个任务
DZSZ:
MOV @R0,DPH
INC R0
MOV @R0,DPL
INC R0
RET
RW1:             ;计数任务一
JB     P1.0,$
JNB    P1.0,$
INC    R7
LJMP   RW1     ;死循环
RW2:             ;计数任务二
JB     P1.1,$
JNB    P1.1,$
DEC    R7
LJMP   RW2     ;死循环
RW3:             ;计数任务三
MOV    R4,#0
CJNE   R4,#250,$ ;准确延时演示,延时时间=250*任务数*定时器时间,
CPL    P1.5
LJMP   RW3     ;死循环
RW4:             ;计数任务四
MOV    R6,#255 ;非准确延时,时间较难计算
BBB:
MOV    R5,#255
DJNZ   R5,$
DJNZ   R6,BBB
CPL    P1.6
LJMP   RW4     ;死循环
RW5:             ;计数任务五
JB     P2.7,$
JNB    P2.7,$
CPL    P1.7
LJMP   RW5     ;死循环
RW6:            ;计数任务六
JB     P1.2,$
JNB    P1.2,$
CPL    P2.2
LJMP   RW6     ;死循环

RW7:             ;计数任务七
LJMP   RW7     ;死循环

RW8:             ;计数任务八
LJMP   RW8     ;死循环

RW9:             ;计数任务九
LJMP   RW9     ;死循环

RW10:             ;计数任务十
LJMP   RW10     ;死循环

RW11:             ;计数任务十一

LJMP   RW11     ;死循环

RW12:             ;计数任务十二
LJMP   RW12     ;死循环

RW13:             ;计数任务十三
CPL P0.0
LJMP   RW13     ;死循环

RW14:             ;计数任务十四
CPL P0.1
LJMP   RW14     ;死循环

RW15:             ;计数任务十五
CPL P0.2
LJMP   RW15     ;死循环

RW16:             ;计数任务十六
CPL P0.3
LJMP   RW16     ;死循环

RW17:             ;计数任务十七
CPL P0.4
LJMP   RW17     ;死循环

RW18:             ;计数任务十八
CPL P0.5
LJMP   RW18     ;死循环

RW19:             ;计数任务十九
CPL P0.6
LJMP   RW19     ;死循环

RW20:             ;计数任务二十
CPL P0.7
LJMP   RW20     ;死循环

END




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表