打印
[ZLG-ARM]

转:哪怕再简单也要注重思路!

[复制链接]
1246|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
即时生效|  楼主 | 2011-12-28 17:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

    给初学者讲授“DIY计算机”的书稿——LED流水灯

    人们时常看到户外动画广告,一会儿从左到右地显示,一会儿又从右到左地显示,这就是流水灯效果,其特征是将想要显示的画面切割成N份,且每次只让其中的一个画面显示,同时让肉眼能够看得清楚。
    假设先让其中的一幅画面显示,接着“立刻”点亮与其相邻的另一幅画面,且同时熄灭前一幅画面,画面切换间隔时间为µs级,由于人眼的反应速度非常之慢,所以无法看清楚画面切换的过程,以至于看起来的效果就是一幅全部点亮的画面,比如,电视画面,这就是人们常说的视觉暂存效应。
    如果在点亮第一幅画面后,延时等待一个固定的时间值(假设延迟时间为ms或s级),再在点亮与其相邻的画面的同时熄灭前一幅画面,接着再延时等待一个固定的时间值……那么就能看到画面象流水一样显示的效果。
    下面将用LED来模拟从右到左的流水灯的显示效果,将“与发光二极管D17-D24相连的JP4”用并行排线连接到“与单片机的P1.0-P1.7口相连的JP31”,然后短接JP39_5与JP39_6,即硬件电路连接完毕(省略图)。由此可以看出,只要单片机I/O口输出高电平1,那么经过反相器转变为低电平后,即可驱动LED发光,反之LED熄灭。
    很显然如果想先点亮最右边第一个LED(D17),那么只要将数据01H传送到P1口即可。通过查看传送指令集,发现可以直接使用“MOV direct,#data”(MOV P1,#01H)指令来实现,那么只要在灯“流动”显示的过程中插入延时程序即可,程序清单1.1就是实现LED流水灯的程序,MAIN为主程序标号,就是程序计数器的PC,即起始地址0000 0000。

程序清单 1.1  LED流水灯程序范例(1)
MAIN: MOV  P1,#01H                          ;01H = 0000 0001 ,P1.0为高电平1,D17发光
      ;执行延时程序Delay                                      
      MOV  P1,#02H                          ;02H = 0000 0010,P1.1为高电平1,D18发光
      ;执行延时程序Delay                                      
      ……
      MOV  P1,#80H                          ;80H = 1000 0000,P1.7为高电平1,D24发光
      ;执行延时程序Delay                                      
      AJMP MAIN                             ;跳转到MAIN,循环执行程序
    虽然这种编程方法也能够达到目的,但效率却很低。通过分析上面的程序可以看出其中的规律,即数据01H、02H、04H、08H、10H、20H、40H、80H中的“1”不断地从右向左移动。由此可见,如果将数据01H存放在累加器A中,即使用“MOV A,#01H”指令,接着将A中的数据传递给P1,然后再想办法让A中的数据01H中的“1”从右向左移动即可,其应用实例如下:
     MOV direct,A                           ;MOV P1,A
    通过查看逻辑运算指令集,发现“RLC A”移位运算指令刚好满足要求。其功能是将累加器A的内容全部向左移动1位,当移位8次之后,最高位D7移到标志位CY,而CY原来的内容则移到累加器最低位D0中,其数据结构为1 0000 0000,即CY=1所有的LED全部熄灭,这就是实现“流水”灯的基本思路,详见程序清单1.2。

程序清单 1.2  LED流水灯程序范例(2)
MAIN:MOV  A,#01H
Loop: MOV  P1,A
      RLC  A                                ;带进位累加器A循环左移
      ;执行延时程序Delay
      AJMP Loop                             ;跳转到Loop处,循环执行程序
    接着开始编写延时程序,那么一条指令的执行时间是多少呢?循环延时程序详见程序清单 6.13。

程序清单 1.3  延时程序范例(1)
        MOV  R7,#0FFH                        ;1个机器周期
Delay2:DJNZ R7,Delay2                       ;2个机器周期(*)
    在执行指令之前R7先减1,然后判断R7是否为0。如果R7≠0,则R7继续做减1操作。与此同时因为延时参数寄存器R7保存的数据为255(0FFH),由于执行1条指令(标有“*”号的指令)为2个机器周期,所以这2个机器周期会重复执行255次。程序实际所耗的准确机器周期为:1+2×255=511个机器周期,延时时间为511×1.1µs =562.1µs。很显然由于人眼的视觉暂存效应,以至于最终看到的效果是LED全部被点亮,因此必须再延长扫描时间,那么最好的办法是使用DJNZ指令再增加一个延时循环,详见程序清单 1.4。

程序清单 1.4  延时程序范例(2)
Delay: MOV   R6,#0FFH                       ;1个机器周期
Delay1: MOV   R7,#0FFH                       ;1个机器周期
Delay2: DJNZ  R7,Delay2                      ;2个机器周期
        DJNZ  R6,Delay1                      ;2个机器周期
    延时时间为[1+(1+2×255+2)×255]×1.1µs=143897.6µs=143.8mS,由此可见,如果觉得延时时间不合适,由于R7处于内层循环,因此修改R7的初值对延时的影响太小,那么可以修改R6寄存器的初值。程序清单 1.5为改进后的LED流水灯程序,程序清单 1.6为翻译为机器码后对应的程序。

程序清单 1.5  LED流水灯程序范例(3)
MAIN: MOV   A,#01H
Loop:  MOV   P1,A
       RLC   A
Delay:MOV   R6,#0FFH                         ;延时时间为143.8mS
Delay1:MOV   R7,#0FFH
Delay2 DJNZ  R7,Delay2
       DJNZ  R6,Delay1
       AJMP  Loop
       ;
       END

程序清单 1.6  LED流水灯程序范例(4)
   地址           指令           助记符                   注释
0000 0000      0111 0100       MOV   A,#01H          ;该指令为2字节
0000 0001      0000 0001
0000 0010*    1111 0101       MOV   P1,A            ;该指令为2字节
0000 0011      1001 0000
0000 0100      0011 0011       RLC   A               ;该指令为1字节
0000 0101      0111 1110       MOV   R6,#0FFH        ;该指令为2字节
0000 0110      1111 1111
0000 0111*    0111 1111       MOV   R7,#0FFH        ;该指令为2字节
0000 1000      1111 1111
0000 1001*   1101 1111       DJNZ  R7,0009H         ;该指令为2字节,跳转到0009H
0000 1010      1111 1110                                                         
0000 1011      1101 1110       DJNZ  R6,0007H         ;该指令为2字节,跳转到0007H
0000 1100      1111 1010                                                         
0000 1101      0000 0001       AJMP  0002H            ;该指令为2字节
0000 1110      0000 0010
   待程序输入正确无误之后,只要将A3实验区的运行开关K11拨到RUN档运行,即可看到LED流水灯效果。
   思考题:如果将“RLC A”指令改为“RL A”,请仔细观察流水灯的效果。

相关帖子

沙发
coco11| | 2011-12-28 19:35 | 只看该作者
:handshake

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

685

帖子

3

粉丝