正文

【018】流水灯花样变换 [51]2006-08-27 22:27:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/wentao/17945.html

分享到:

实验参考: 笨笨工作室-实验九、流水灯花样变换(中断)。(查看)
实验板:   FB51A。(查看)

实验目的: 掌握在中断程序中处理多个按键动作的响应方法。

实验现象: 进入程序后,程序作双向流水灯;按下k1键,程序作左向流水灯; 按下k2按键程序作右向流水灯; 按下k3键两个亮点从两边向中间移动; 按下k3键两个亮点从中间向两边移动。



在上个实验(016中断的应用中对断点的保护)中,只用了一个按键触发中断, 而本次实验中断程序要对多个按键动作进行响应, 灯光变换的花样有4种,用4个按键k1,k2,k3,k4切换。

显示部分电路:

键盘部分电路(图中K0对应程序中K1……K3对应K4):

思路:主程序中执行左右流水灯,在中断服务程序中,首先读取按键状态,然后延时10ms,再次读取按键状态。把两次获得的按键状态比较,如果不同,就表示是抖动,退出中断;否则,就去判断是哪个按键按下。如果是k1,就执行左跑马灯;如果是k2,就执行右跑马灯;如果是k3,就执行亮点向中间移动;如果是k4,就执行亮点向两边移动。

值得注意的是: 在中断服务程序中,应该尽量的使得任务简化,不要让中断服务程序作过多复杂的任务,而要尽量把这些复杂的任务放到主程序中间去完成

本着这一原则, 可以采用置标志位的方法。即在主程序中设定一个标志位,不断的对这个标志进行查询:如果是标志为状态1,就执行双向跑马灯;如果是状态2,就执行左向跑马灯;如果是状态3,就执行右向跑马灯,依次类推。而在中断服务程序中,只需要进行如下工作:去抖动,键识别,改变标志位。

这里我们用寄存器r0的内容作为标志,当它里面的内容是0ffh时,执行左右跑马灯程序;为01h时,执行左跑马灯;02h时执行右跑马灯;03h时执行两个亮点向中间移动;04h时执行两个亮点象两边移动。

下面是主程序和中断程序的流程图


程序如下:

          org   0000h
          ljmp  start
          org   0003h   
          ljmp  ext1
          org   0020h
start:    mov   r0, #0ffh        ; 对r0赋值,r0为所设标志位
          setb  ea               ; 开中断
          setb  ex0              ; 允许外部中断0申请中断
          setb  it0              ; 外部中断0为跳变方式触发
          mov   sp, #70h         ; 设置中断

loop0:    cjne  r0, #0ffh, loop1 ; r0不为ff, 转到loop1
          ajmp  main_light       ; 否则执行左右流水灯
loop1:    cjne  r0, #01h,  loop2 ; r0不为01, 转到loop2
          ajmp  k1_light         ; 否则执行左向流水灯
loop2:    cjne  r0, #02h,  loop3 ; r0不为02, 转到loop3
          ajmp  K2_light         ; 否则执行右向流水灯
loop3:    cjne  r0, #03h,  loop4 ; r0不为03, 转到loop4
          ajmp  k3_light         ; 否则执行双亮点向中间移动
loop4:    cjne  r0, #04h,  loop5 ; r0不为04, 转到loop5
          ajmp  k4_light         ; 否则执行双亮点向两边移动
loop5:    ajmp  loop0            ; 返回重新查询

;===========================中断服务程序===========================

ext1:     clr   ea               ; 关中断
          push  acc
          push  psw
         
          mov   a, p1            ; 读入键值
          anl   a, #0fh          ; 屏蔽高四位
          mov   30h, a           ; 键状态存入30h
          lcall del10ms
          mov   a, p1            ; 再次读入键值
          anl   a, #0fh
          cjne  a, 30h, pass     ; 两次键值不同,是抖动,退出中断
          ajmp  k1_check         ; 如果相等,进行键识别
         
; 键识别部分

k1_check: cjne  a, #0eh, k2_check ; 不是k1, 判断是不是k2
          mov   r0, #01h          ; 是k1, 置标志为01
          ajmp  pass
k2_check: cjne  a, #0dh, k3_check ; 不是k2, 判断是不是k3
          mov   r0, #02h          ; 是k2, 置标志为02
          ajmp  pass
k3_check: cjne  a, #0bh, k4_check ; 不是k3, 判断是不是k4
          mov   r0, #03h          ; 是k3, 置标志为03
          ajmp  pass
k4_check: cjne  a, #07h, pass     ; 不是k4, 退出中断
          mov   r0, #04h          ; 是k4, 置标志为04
          ajmp  pass
         
pass:     pop   psw               ; 现场恢复
          pop   acc
          setb  ea                ; 开中断
          reti                    ; 中断返回
;======================================================================

main_light: mov   r7, #08h  ; 左右流水灯程序
            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:     mov   r1, a
            mov   p0, a
            lcall del100ms
            rr    a
            djnz  r6, r_loop
            ajmp  loop0
           
k1_light:   mov   r1, a      ; 左向流水灯
            mov   p0, a
            lcall del100ms
            rl    a
            mov   r1, a
            ajmp  loop0
           
k2_light:   mov   r1, a      ; 右向流水灯
            mov   p0, a
            lcall del100ms
            rr    a
            mov   r1, a
            ajmp  loop0
           
k3_light:   mov   p0, #07eh ; 双亮点向中间移
            lcall del100ms
            mov   p0, #0bdh
            lcall del100ms
            mov   p0, #0dbh
            lcall del100ms
            mov   p0, #0e7h
            lcall del100ms
            ajmp  loop0
           
k4_light:   mov   p0, #0e7h ; 双亮点向两边移
            lcall del100ms
            mov   p0, #0dbh
            lcall del100ms
            mov   p0, #0bdh
            lcall del100ms
            mov   p0, #07eh
            lcall del100ms
            ajmp  loop0
           
del10ms:                      ; 10ms延时子程序(12M)
           mov  r5, #20
temp1:     mov  r4, #248
           djnz r4, $
           djnz r5, temp1
           ret
        
del100ms:  mov  r3, #0c3h     ;100.036ms
temp2:     mov  r2, #0ffh     ;511us
           djnz r2, $
           djnz r3, temp2
           ret
          
end


用Proteus仿真通过,原理图如下:


实验结果: 下载到板上测试, 结果与预计相符。 

阅读(6506) | 评论(2)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册