正文

【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   0020hstart:    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  passk2_check: cjne  a, #0dh, k3_check ; 不是k2, 判断是不是k3          mov   r0, #02h          ; 是k2, 置标志为02          ajmp  passk3_check: cjne  a, #0bh, k4_check ; 不是k3, 判断是不是k4          mov   r0, #03h          ; 是k3, 置标志为03          ajmp  passk4_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, #0fehl_loop:     mov   r1, a     ; r1保存现在亮点位置,做样式变换时从该处开始            mov   p0, a            lcall del100ms            rl    a            djnz  r7, l_loop            mov   a, #0bfhr_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, #20temp1:     mov  r4, #248           djnz r4, $           djnz r5, temp1           ret         del100ms:  mov  r3, #0c3h     ;100.036mstemp2:     mov  r2, #0ffh     ;511us           djnz r2, $           djnz r3, temp2           ret           end 用Proteus仿真通过,原理图如下: 实验结果: 下载到板上测试, 结果与预计相符。 

阅读(6645) | 评论(2)


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

评论

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