第2章 51单片机基础实例

本章主要介绍以下几个单片机的基础实例程序:

● 简单点亮发光二极管实例

● 跑马灯实例

● 流水灯实例

● 查0~9平方表实例

● 受控输出实例

● 比较输入数大小实例

● 交通灯控制器实例

● 蜂鸣器发音实例

● 单片机演奏音乐实例

● 软件陷阱实例

2.1 简单点亮发光二极管实例

单片机最简单的实例之一就是点亮发光二极管(LED)闪烁。本节通过点亮1只发光二极管的实例来介绍单片机的I/O口操作。

本节首先介绍单片机I/O口结构的基础知识,接着介绍实例的硬件电路,然后给出了实例程序,最后将分析操作单片机的I/O口的技巧与注意点。

2.1.1 基础知识

8051单片机有4个并行I/O口:P0~P3。这4个I/O口中只有P0口是真正的双向口,P1~P3是准双向口,P3口还具有第二功能,为系统提供一些控制信号。4个并行I/O口的结构如表2-1所示。由I/O口结构可知,P0口的输出三态门由两只场效应管(FET)组成,所以是一个真正的双向口,同时可以提供较强的输出高电平(拉电流)和低电平(灌电流)驱动能力;P1~P3口中,上拉电阻代替了场效应管,输出缓冲器不是三态的,因此不是真正的双向口,只能称为准双向口,同时这些I/O口的输出高电平驱动能力较弱,只能提供较强的输出低电平驱动能力。因此,在使用I/O口直接驱动LED等电流负载时,需要使用输出低电平驱动的接法。

表2-1 并行l/O口的结构

2.1.2 硬件电路图

本实例中,硬件电路主要包括8051单片机最小系统电路(包括5V电源,正极接40引脚,负极(地)接20引脚;振荡电路,使用晶体振荡器,接18、19脚;复位电路;EA引脚接到正电源端)和发光二极管LED电路(由1只LED和1只限流电阻串联而成),具体的连接原理电路图如图2-1所示。当P1.0引脚输出低电平时,点亮LED;当P1.0引脚输出高电平时,LED熄灭。

图2-1 点亮发光二极管原理电路图

2.1.3 软件程序设计

要实现LED的闪烁效果需要通过程序控制单片机连接到LED的I/O引脚,点亮LED,延时一段时间后,再控制I/O引脚使LED熄灭,如此循环就可以实现LED的闪烁。下面,着重介绍延时程序,并给出完整的软件程序实例。

1.延时程序

首先,通过下面的代码演示单片机如何通过程序实现延时一段时间。

    ;延时子程序
    DELAY:
        MOV  R7,#10H                                                               ;(1)
    DELAY0:
        MOV  R6,#7FH                                                               ;(2)
    DELAY1:
        MOV  R5,#7FH                                                               ;(3)
        DJNZ R5,$                                                                  ;(4)
        DJNZ R6,DELAY1                                                             ;(5)
        DJNZ R7,DELAY0                                                             ;(6)
        RET                                                                        ;(7)

程序(1)为数据传送指令,该指令的作用为将数据10H传送到寄存器R7中。8051单片机执行程序(1)~程序(3)后,寄存器R5、R6、R7的值分别为7FH、7FH和10H。程序(4)为减1不为0转移指令,该指令的作用为将寄存器R5中的数据减1,如果结果不为0,则程序跳转。其中“$”符号表示该指令的地址,所以若减1不为0则程序发生跳转,再次执行程序(4)。同理,程序(5)为将寄存器R6中的数据减1,如果结果不为0,则程序跳转到标号“DELAY1”处继续执行。程序(7)为子程序返回指令,执行该指令使程序返回调用子程序时的断点,继续执行断点之后的程序。

以上代码实例使用了数据传送指令和控制转移指令,8051单片机的数据传送指令及控制转移指令如表2-2、表2-3所示。表2-2、表2-3中的其他一些数据传送指令及控制转移指令将在后面的实例中陆续详细介绍。

表2-2 数据传送指令

表2-3 控制转移指令

以上代码实例是一个完整的子程序。所谓子程序,就是完成确定任务,并能被其他程序反复调用的程序代码段,子程序在结构上具有通用性和独立性。子程序的编写必须注意以下几点:

● 子程序调用使用LCALL指令。

● 子程序必须通过RET指令返回。

● 子程序第一条必须有标号,以实现LCALL指令的调用。

● 正确传递入口参数和出口参数。

● 子程序需要注意现场的保护和恢复。

● 如果需要子程序嵌套,应注意嵌套深度与堆栈区大小的问题。

该延时子程序,可以实现约0.5秒的延时,下面看看如何来计算延时子程序的延时时间。8051单片机的一个机器周期包括12个时钟周期,本实例中单片机晶振为12MHz,则它的1个时钟周期是1/12微秒,1个机器周期是1微秒。DJNZ指令是双周期指令,执行1次要2个微秒,延时子程序一共执行258064次DJNZ指令,一共为516128微秒,约为0.5秒。

2.程序全貌

本实例的软件程序全貌如下:

    ;-----------------------------------
    ;                   简单点亮发光二极管实例
    ;功能:点亮发光管LED并闪烁
    ;-----------------------------------
    LED_PIN       EQU        P1.0                                                      ;(1)

    ORG 0000H                ;伪指令,指定程序从0000H开始存放
    LJMP  MAIN               ;跳转指令,程序跳转到MAIN处
    ORG 0100H                ;伪指令,指定以下程序从0100H开始存放
    MAIN:
        MOV  SP,#60H         ;给堆栈指针赋初值                                   (2)
    LIGHT:
        SETB  LED_PIN        ;置一P1.0,LED灭                                    (3)
        LCALL  DELAY         ;调延时子程序                                       (4)
        CLR  LED_PIN         ;清零P1.0,LED亮                                    (5)
        LCALL  DELAY         ;调延时子程序                                       (6)
        SJMP  LIGHT          ;跳转,程序继续                                     (7)

    ;延时子程序
    DELAY:
        MOV  R7,#10H
    DELAY0:
        MOV  R6,#7FH
    DELAY1:
        MOV  R5,#7FH
        DJNZ R5,$
        DJNZ R6,DELAY1
        DJNZ R7,DELAY0
        RET
    END

程序(1)为伪指令,伪指令是在汇编程序中起某种控制作用的特殊命令,其格式与通常的操作指令一样,并可加在汇编程序的任何地方,但它们并不产生实际的机器指令。程序(1)的作用是定义常数,也就是说,在该伪指令以下程序中出现的LED_PIN都是指代P1.0。8051单片机编程中常用的伪指令如表2-4所示。

表2-4 常用伪指令

8051单片机在上电复位后程序计数器PC中的值为0000H,也就是说程序是从0000H单元开始执行的。通过伪指令ORG 0000H指定程序从0000H单元开始存放,并在该单元写入跳转指令LJMP MAIN,使程序跳转到MAIN处开始执行。“MAIN:”称为标号,它代表了当前行的程序存储器地址。

程序(2)为给堆栈指针赋初值指令。所谓堆栈是一个RAM区域,堆栈存放和取用数据的方式比较特殊:先进后出,后进先出。堆栈的数据传输指令有两条,即PUSH和POP指令,堆栈的操作还涉及一个寄存器:堆栈指针SP。每当执一次PUSH指令时,SP的值就自动加1,然后数据被放到SP所指示的RAM单元中。每当执行一次POP指令,数据从SP所指示的RAM单元中取出,然后SP的值自动减1。由于上电复位后,SP的初始值为07H,这样就使堆栈数据从08H单元开始往后存放,而08H到1FH这个区域正是8051 单片机的第二、三、四工作寄存器区,经常要被使用,这会造成数据的混乱。所以使用MOV SP,#60H指令设置堆栈指针,把堆栈设置在从60H开始的RAM单元中。

程序(3)、程序(5)为位操作指令,8051单片机的位操作指令见表2-5。

表2-5 位操作指令

通过直接寻址位取反指令CPL,程序(3)~(7)也可写作如下:

    LIGHT:
        CPL       LED_PIN        ;取反P1.0,改变LED的亮灭状态
        LCALL     DELAY          ;调延时子程序
        SJMP LIGHT               ;跳转,程序继续

3.运行结果

本实例的运行结果为LED不停闪烁。

2.1.4 技巧总结

本实例从单片机点亮1只发光二极管出发,演示8051单片机是如何操作I/O口的。在单片机I/O口操作中应注意以下的技巧。

● 硬件连接过程中应注意各I/O口的内部结构,选择合适的引脚及连接方式。一般来说,对于I/O口驱动电流负载的情况,应采用输出低电平驱动电路的形式。对于许多新型的51内核的单片机,引脚提供了输出20mA电流的LED驱动能力,输出高电平时也可以直接驱动LED。

● 操作I/O口的指令主要是SETB bit、CLR bit、CPL bit。