2.2 跑马灯实例

在上一节点亮1只LED的基础上,让我们来看看如何控制多只LED实现跑马灯效果。

2.2.1 硬件电路图

本实例中,硬件电路和上一节的硬件电路相似,为了实现跑马灯,本实例电路连接了8只LED,原理电路图如图2-2所示。

图2-2 跑马灯原理电路图

2.2.2 软件程序设计

控制多只LED实现跑马灯效果可以有多种实现方式,下面给出其中两种,请对比这两种实现方式的优劣。

1.程序全貌

首先,使用上节学习的直接寻址位置1指令SETB bit和直接寻址位清0指令CLR bit控制P1口实现跑马灯效果,以下为程序实例。

    ;-----------------------------------
    ;                   跑马灯实例
    ;功能:循环轮流点亮8只发光管LED
    ;-----------------------------------
    LED1_PIN EQU        P1.0
    LED2_PIN EQU        P1.1
    LED3_PIN EQU        P1.2
    LED4_PIN EQU        P1.3
    LED5_PIN EQU        P1.4
    LED6_PIN EQU        P1.5
    LED7_PIN EQU        P1.6
    LED8_PIN EQU        P1.7

    ORG 0000H                     ;伪指令,指定程序从0000H开始存放
    LJMP  MAIN                    ;跳转指令,程序跳转到MAIN处

    ORG 0100H                     ;伪指令,指定以下程序从0100H开始存放
    MAIN:
        MOV  SP,#60H              ;给堆栈指针赋初值
        MOV  P1,#0FFH             ;给P1赋初值,LED全灭                                (1)
    LIGHT:
        CLR       LED1_PIN        ;清零P1.0,LED1亮                                   (2)
        LCALL     DELAY           ;调延时子程序                                       (3)
        SETB LED1_PIN             ;置一P1.0,LED1灭                                   (4)
        CLR       LED2_PIN        ;清零P1.1,LED2亮                                   (5)
        LCALL     DELAY           ;调延时子程序                                       (6)
        SETB LED2_PIN             ;置一P1.1,LED2灭                                   (7)
        CLR       LED3_PIN        ;清零P1.2,LED3亮                                   (8)
        LCALL     DELAY           ;调延时子程序                                       (9)
        SETB LED3_PIN             ;置一P1.2,LED3灭                                   (10)
        CLR       LED4_PIN        ;清零P1.3,LED4亮                                   (11)
        LCALL     DELAY           ;调延时子程序                                       (12)
        SETB LED4_PIN             ;置一P1.3,LED4灭                                   (13)
        CLR       LED5_PIN        ;清零P1.4,LED5亮                                   (14)
        LCALL     DELAY           ;调延时子程序                                       (15)
        SETB LED5_PIN             ;置一P1.4,LED5灭                                   (16)
        CLR       LED6_PIN        ;清零P1.5,LED6亮                                   (17)
        LCALL     DELAY           ;调延时子程序                                       (18)
        SETB LED6_PIN             ;置一P1.5,LED6灭                                   (19)
        CLR       LED7_PIN        ;清零P1.6,LED7亮                                   (20)
        LCALL     DELAY           ;调延时子程序                                       (21)
        SETB LED7_PIN             ;置一P1.6,LED7灭                                   (22)
        CLR       LED8_PIN        ;清零P1.7,LED8亮                                   (23)
        LCALL     DELAY           ;调延时子程序                                       (24)
        SETB LED8_PIN             ;置一P1.7,LED8灭                                   (25)
        AJMP LIGHT                ;跳转,程序继续                                     (26)
    ;延时子程序
    DELAY:
        MOV  R7,#10H
    DELAY0:
        MOV  R6,#7FH
    DELAY1:
        MOV  R5,#7FH
        DJNZ R5,$
        DJNZ R6,DELAY1
        DJNZ R7,DELAY0
        RET
    END

本实例也可使用循环左移指令和循环右移指令来实现跑马灯效果,循环左移指令和循环右移指令的功能见表2-6。

表2-6 循环左移指令和循环右移指令

(1)~(26)程序替换为如下程序,运行结果不变。

    LIGHT:
        MOV  R0,#08H         ;给R0赋初值08H,循环右移8次
        MOV  A,#0FEH         ;给A赋初值0FEH,即11111110
    LOOP:
        RR        A          ;右移1位
        MOV  P1,A            ;输出显示
        LCALL     DELAY      ;调延时子程序
        DJNZ R0,LOOP         ;循环右移8次
        SJMP LIGHT           ;跳转,程序继续

2.运行结果

该实例的运行结果为8只LED循环轮流点亮。

2.2.3 技巧总结

本实例技巧总结如下:

● 同样的运行结果,使用合适的指令可以大大减少代码量,节省程序空间。

● 循环移位指令的应用——乘除法运算:左移1 次 = 无符号数乘2 运算,右移1次 = 有符号数除2运算。