单片机学习之十三:流水灯花样变换(中断)
进入程序后,程序作双向跑马灯;按下k0键,程序作左向跑马灯;按下k1按键程序作右向跑马灯;按下k2键两个亮点从两边向中间移动;按下k3键两个亮点从中间向两边移动。
二、实验目的
掌握在中断程序中处理多个按键动作的响应方法
三、实验任务分析:
(注意:在作这个试验的时候,不要忘了把JMP0跳线置于1、2的位置,选择二极管显示单元。)
在前面的两个中断方式响应按键动作的试验中,我们只对一个按键动作做出响应,难度比较小。
而在这个程序中,我们的中断程序要对多个按键动作进行响应, 灯光变换的花样有4种,用不同的按键切换。那么,这种问题又应该如何处理呢?
我们可以这样作:主程序中,我们作左右跑马灯,相信大家已经很熟啦。
在中断服务程序中,我们首先读取按键状态,然后延时10ms,再次读取按键状态。把两次获得的按键状态比较,如果不同,就表示是抖动,退出中断;否则,就去判断是哪个按键按下。如果是k0,就执行左跑马灯;如果是k1,就执行右跑马灯;如果是k2,就执行亮点向中间移动;如果是k3,就执行亮点向两边移动。
这样的思路总体是对的,但是有一点需要注意:我们在写程序的时候,在中断服务程序中,应该尽量的使得任务简化,不要让中断服务程序作过多复杂的任务,而要尽量把这些复杂的任务放到主程序中间去完成。
按照这样的一个思路,我们的做法如下:
在主程序中设5个标志,然后不断的对这几个标志进行查询:如果是标志1,就执行双向跑马灯;如果是标志2,就执行左向跑马灯;如果是标志3,就执行右向跑马灯,依次类推。
而在中断服务程序中,我们只需要进行如下工作:去抖动,键识别,改变标志,就可以啦。
该程序中,我们用寄存器r0中的内容作为标志,当它里面的内容是0ffh时,执行左右跑马灯程序;为00h时,执行左跑马灯;01h时执行右跑马灯;02h时执行两个亮点向中间移动;03h时执行两个亮点象两边移动。
现在来看看主程序和中断服务程序的流程图吧:
下面就是按照这个思路编写的程序,这个程序的结构略微复杂,大家要注意。
四、实验程序如下:
org 0000h
ajmp start
org 0013h
ajmp ext1
org 0020h
start: clr p1.5
mov r0,#0ffh ;对r0赋初值,r0即为我们设的标志,
setb ea ;开中断
setb ex1 ;允许外部中断1申请中断
setb it1 ;设置外部中断1跳变方式触发
mov sp,#70h ;设置堆栈
loop0: cjne r0,#0ffh,loop1 ; 如果r0中的内容不是0ffh,转去loop1
ajmp main_light ;否则,执行左右跑马灯
loop1: cjne r0,#00h,loop2 ;如果r0中的内容不是00h,转去loop2
ajmp k0_light ;否则,执行左向跑马灯
loop2: cjne r0,#01h,loop3 ;如果r0中的内容不是01h,转去loop3
ajmp k1_light ;否则,执行右向跑马灯
loop3: cjne r0,#02h,loop4 ;如果r0中的内容不是02h,转去loop4
ajmp k2_light ;否则,执行双亮点向中间移动
loop4: cjne r0,#03h,loop5 ;如果r0中的内容不是03h,返回重新开始查询
ajmp k3_light ;否则,执行双亮点向两边移动
loop5: ajmp loop0 ;返回重新开始查询
ext1: clr ea ;关闭中断
push acc ;现场保护
push psw
mov a,p1 ;读入按键状态
anl a,#0fh ;屏蔽高四位
mov 30h,a ;把键盘状态值保存在30h
mov a,p1 ;再次读入按键状态
anl a,#0fh ;屏蔽高四位
cjne a,30h,pass ;两次的按键值如果不相等,表示是抖动,退出中断
ajmp k0_check ;如果相等,转去键识别程序
;以下是按键识别程序
k0_check: cjne a,#0dh,k1_check ;如果不是k0按下,转去判断是否k1按下
ajmp k0_manage ;否则,转去k0的按键处理程序
k1_check: cjne a,#0eh,k2_check ;如果不是k1按下,转去判断是否k2按下
ajmp k1_manage ;否则,转去k1的按键处理程序
k2_check: cjne a,#0bh,k3_check ;如果不是k2按下,转去判断是否k3按下
ajmp k2_manage ;否则,转去k2的按键处理程序
k3_check: cjne a,#07h,pass ;如果不是k3按下,退出中断
ajmp k3_manage ;否则,转去k3的按键处理程序
;以下是各按键相应的处理程序,
k0_manage: mov r0,#00h ;置标志2
ajmp pass
k1_manage: mov r0,#01h ;置标志3
ajmp pass
k2_manage: mov r0,#02h ;置标志4
ajmp pass
k3_manage: mov r0,#03h :置标志5
ajmp pass
pass: pop psw ;恢复现场
pop acc
setb ea ;开中断
reti ;中断返回
main_light: mov r7,#08h ;main_light是左右跑马灯程序
mov r6,#06h
mov a,#0feh
l_loop: mov r1,a ;用r1保存现在的亮点位置,便于变换灯光时从该位置开始
mov p0,a
lcall del100ms
rl a
djnz r7,l_loop
mov a,#0bfh
r_loop: mo
单片机流水灯中 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)