最简单的51单片机多任务代码
时间:11-29
来源:互联网
点击:
;本51多任程序原理是设置了多个栈位置和在中断中改写栈指针的方法进行任务切换。
;由于使用了多个栈,调用时不能有太多的嵌套调用,以免超出栈的工作区(48个字节),使程序出错。
;这个程序只是为了做个多任务的试验,实用性还有侍验证。
;当然这种思路是来自PC操作系统,我个人认为把PC编程上的事件驱动引入51是一种很好的方法。
;在另一程序内已使用过,感觉还不错。(感兴趣的朋友可向我索取)
;----------------------------------------------
;由于我用的MCS51程序有BUG,在调试时MCS51软件的栈区数变化和数据区不一至。即:栈区数变化
;了对应的数据区数据没有按实际的应同时变化(因用的是同一存储空间)。
;(实际两数据的地址和内容都是相同的,只是模拟软件内部不同步)。要用手动改写才能正常工作。
;具体方法是:栈区数据变化时手动改写数据区对应地址的数据与栈内数据对应。
;请使用该软件的朋友用到栈区模拟调试时注意(否则程序就会飞掉)。
;----------------------------------------------
org 0000h;www.51hei.com2004.6028-89951522
;mail:xch1106@163.comQQ:15552363
jmp zcx;去主程序
org 001bh
call tim;定时中断1入口
reti
zcx:
mov sp,#60h;置任务1栈顶位置,任务2 90h,任务3 0c0h
mov tmod,#10h;设定时器1工作方式2
mov th1,#0f3h;设高位初值
mov tl1,#00h;设低位初值
setb ea;开中断
setb et1;开定时中断
setb tr1;开启计数器
mov 00h,#00h;任务计数器初始化
clr 00h;全部栈初始化完成标志清0
clr 01h;任务1栈初始化标志位清0
clr 02h;任务2栈初始化标志位清0
clr 03h;任务3栈初始化标志位清0
setb rs0;选择寄存器组
clrrs1
;==============================
cshsp1: jnb 01h,$;等侍定时中断,以便自动初始化任务1栈数据
;mov 01h,sp
jb 00h,main1;全部栈区数据初始化完成则进入任务1
jmp cshsp2;否则->初始化任务2
main1:;任务1
nop;你的代码
nop
nop
nop
nop
jmp main1
;-------------------------------
cshsp2: mov sp,#90h;置任务2栈顶位置
jnb 02h,$;等侍定时中断,以便自动初始化任务2栈数据
;mov 02h,sp
jb 00h,main2;全部栈区数据初始化完成则进入任务2
jmp cshsp3
main2:;任务2
nop
nop
nop
nop
nop
jmp main2
;---------------------------------------
cshsp3: mov sp,#0c0h;置任务3栈顶位置
jnb 03h,$;等侍定时中断,以便自动初始化任务3栈数据
;mov 03h,sp;全部栈区数据初始化完成则进入任务3
main3:;任务3
nop
nop
nop
nop
nop
jmp main3
;;===========================================
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
tim:push a;定时1中断子程序
push psw
clr tr1;关闭定时器
clr et1;关闭定时中断
;使用资源:定时器1,定时器1中断,0组寄存器,
clr rs0;选择寄存器组
clr rs1
mov th1,#0f3h;设高位初值 (中断时间的长短)
mov tl1,#00h;设低位初值 (在操作系统中可能叫时间片参数)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
jb 00h,rwqh;00H为1则初始化已完成(初始化只进行3次中断即全部初始化1次)
;就不再进行初始化,而进行任务切换操作
;------------------- sp 1 2 3初始化栈数据
jb 01h,stsp1
mov 01h,sp;保存当前的栈位置(任务1)
;读取当前栈内容并全部重压入1次。
;相当于在栈区做了一次备份,任务切换时使用
;本次中断返回时将弹出原来的数据,备份的则还在栈内。
push 61h
push 62h
push 63h
push 64h
push 65h
push 66h
setb 01h
jmp end1
stsp1:
jb 02h,stsp2
mov 02h,sp;保存当前的栈位置(任务2)
;读取当前栈内容并全部重压入1次。
push 91h
push 92h
push 93h
push 94h
push 95h
push 96h
setb 02h
jmp end1
stsp2:
jb 03h,rwqh
mov 03h,sp;保存当前的栈位置(任务3)
;读取当前栈内容并全部重压入1次。(初始化栈区数据的方法)
push 0c1h
push 0c2h
push 0c3h
push 0c4h
push 0c5h
push 0c6h
setb 03h
setb 00h
jmp end1
;-------------------
rwqh:
;;;;;;;;;;;;;;;;;;;切换任务,每中断1次切换1次。
inc 00h;任务计数
cjne r0,#01h,rwqh2;当前任务为3切换到任务1(改变SP位置,得到切换任务的目的)
mov 03h,sp
mov sp,01h
rwqh2:
cjne r0,#02h,rwqh3;当前任务为1切换到任务2
mov 01h,sp
mov sp,02h
rwqh3:
cjne r0,#03h,end1;当前任务为2切换到任务3
mov 02h,sp
mov sp,03h
mov 00h,#00h
end1:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
setb et1
setb tr1
pop psw
pop a
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
参考资料:http://www.51hei.com/mcu/1325.html
;由于使用了多个栈,调用时不能有太多的嵌套调用,以免超出栈的工作区(48个字节),使程序出错。
;这个程序只是为了做个多任务的试验,实用性还有侍验证。
;当然这种思路是来自PC操作系统,我个人认为把PC编程上的事件驱动引入51是一种很好的方法。
;在另一程序内已使用过,感觉还不错。(感兴趣的朋友可向我索取)
;----------------------------------------------
;由于我用的MCS51程序有BUG,在调试时MCS51软件的栈区数变化和数据区不一至。即:栈区数变化
;了对应的数据区数据没有按实际的应同时变化(因用的是同一存储空间)。
;(实际两数据的地址和内容都是相同的,只是模拟软件内部不同步)。要用手动改写才能正常工作。
;具体方法是:栈区数据变化时手动改写数据区对应地址的数据与栈内数据对应。
;请使用该软件的朋友用到栈区模拟调试时注意(否则程序就会飞掉)。
;----------------------------------------------
org 0000h;www.51hei.com2004.6028-89951522
;mail:xch1106@163.comQQ:15552363
jmp zcx;去主程序
org 001bh
call tim;定时中断1入口
reti
zcx:
mov sp,#60h;置任务1栈顶位置,任务2 90h,任务3 0c0h
mov tmod,#10h;设定时器1工作方式2
mov th1,#0f3h;设高位初值
mov tl1,#00h;设低位初值
setb ea;开中断
setb et1;开定时中断
setb tr1;开启计数器
mov 00h,#00h;任务计数器初始化
clr 00h;全部栈初始化完成标志清0
clr 01h;任务1栈初始化标志位清0
clr 02h;任务2栈初始化标志位清0
clr 03h;任务3栈初始化标志位清0
setb rs0;选择寄存器组
clrrs1
;==============================
cshsp1: jnb 01h,$;等侍定时中断,以便自动初始化任务1栈数据
;mov 01h,sp
jb 00h,main1;全部栈区数据初始化完成则进入任务1
jmp cshsp2;否则->初始化任务2
main1:;任务1
nop;你的代码
nop
nop
nop
nop
jmp main1
;-------------------------------
cshsp2: mov sp,#90h;置任务2栈顶位置
jnb 02h,$;等侍定时中断,以便自动初始化任务2栈数据
;mov 02h,sp
jb 00h,main2;全部栈区数据初始化完成则进入任务2
jmp cshsp3
main2:;任务2
nop
nop
nop
nop
nop
jmp main2
;---------------------------------------
cshsp3: mov sp,#0c0h;置任务3栈顶位置
jnb 03h,$;等侍定时中断,以便自动初始化任务3栈数据
;mov 03h,sp;全部栈区数据初始化完成则进入任务3
main3:;任务3
nop
nop
nop
nop
nop
jmp main3
;;===========================================
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
tim:push a;定时1中断子程序
push psw
clr tr1;关闭定时器
clr et1;关闭定时中断
;使用资源:定时器1,定时器1中断,0组寄存器,
clr rs0;选择寄存器组
clr rs1
mov th1,#0f3h;设高位初值 (中断时间的长短)
mov tl1,#00h;设低位初值 (在操作系统中可能叫时间片参数)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
jb 00h,rwqh;00H为1则初始化已完成(初始化只进行3次中断即全部初始化1次)
;就不再进行初始化,而进行任务切换操作
;------------------- sp 1 2 3初始化栈数据
jb 01h,stsp1
mov 01h,sp;保存当前的栈位置(任务1)
;读取当前栈内容并全部重压入1次。
;相当于在栈区做了一次备份,任务切换时使用
;本次中断返回时将弹出原来的数据,备份的则还在栈内。
push 61h
push 62h
push 63h
push 64h
push 65h
push 66h
setb 01h
jmp end1
stsp1:
jb 02h,stsp2
mov 02h,sp;保存当前的栈位置(任务2)
;读取当前栈内容并全部重压入1次。
push 91h
push 92h
push 93h
push 94h
push 95h
push 96h
setb 02h
jmp end1
stsp2:
jb 03h,rwqh
mov 03h,sp;保存当前的栈位置(任务3)
;读取当前栈内容并全部重压入1次。(初始化栈区数据的方法)
push 0c1h
push 0c2h
push 0c3h
push 0c4h
push 0c5h
push 0c6h
setb 03h
setb 00h
jmp end1
;-------------------
rwqh:
;;;;;;;;;;;;;;;;;;;切换任务,每中断1次切换1次。
inc 00h;任务计数
cjne r0,#01h,rwqh2;当前任务为3切换到任务1(改变SP位置,得到切换任务的目的)
mov 03h,sp
mov sp,01h
rwqh2:
cjne r0,#02h,rwqh3;当前任务为1切换到任务2
mov 01h,sp
mov sp,02h
rwqh3:
cjne r0,#03h,end1;当前任务为2切换到任务3
mov 02h,sp
mov sp,03h
mov 00h,#00h
end1:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
setb et1
setb tr1
pop psw
pop a
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
参考资料:http://www.51hei.com/mcu/1325.html
51单片机多任务代 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)