
任务三 数码管显示
任务描述
这里的数码管其实就是LED灯,七段数码管是由7个LED组成的“8”字形的显示
设备,每个LED一个段,分别用a、b、c、d、e、f、g和dp表示,可显示数字0~9或
字母A~F,另外还有一个用于表示小数点的LED,共8个LED,如图
1 23所示。
编写一个程序控制单片机在4位七段数码管中显示数字“1234”,并让显示的内容每隔1s自动加1。
任务分析
本任务介绍单片机如何控制七段数码管显示,如何控制多个数码管显示,学习几个常见的编程指令,了解循环程序设计格式、数码管扫描显示方法及原理。掌握七段数码管的电路连接,掌握查表的编程方法。

任务实施
图1-23 七段
数码管
一、七段数码管控制方式1.七段数码管结构
七段数码管有共阴极和共阳极两种,共阴极就是将所有发光二极管的阴极共同连接在一个COM点,阳极分别用a、b、c、d、e、f、g和dp表示;共阳极就是将所有发光二极管的阳极共同连接在一个COM点,阴极分别用a、b、c、d、e、f、g和dp表示,如图1-24所示。

图1-24 共阴极、共阳极七段数码管电路
(a)共阴极;(b)共阳极
七段数码管的显示电路可分为静态显示电路和动态显示电路。数码管不间断地持续显示为静态显示,一般用于只有1个七段数码管的情况下。动态显示的数码管处于高频率的通断刷新中,一般用于有多个七段数码管组合的情况下,如图1-25所示。

图1-25 四位七段数码管
2.静态显示
共阳极数码管使用时,将COM与VCC连接,然后在每个阴极接一个限流电阻,再与驱动电路连接或直接接到单片机引脚,如图1-26所示。

图1-26 七段数码管连接电路
当阴极对应的引脚输出低电平时,相应的LED点亮,根据不同引脚电平的输出组合可以显示不同数字。
共阴极数码管使用时,先将COM连接GND,然后在每个阳极接一个限流电阻,再与驱动电路连接或直接接到单片机引脚,如将阳极直接单片机引脚,则需给引脚加设2kΩ左右上拉电阻增加驱动电流。
静态显示的电路优点是控制简单,只要在8个数据端口输入相应数字的编码即可,易于编写程序。以共阴极数码管为例,显示数字1时让b、c两段点亮即可,假如a~dp分
别连接P0.0~P0.7,那么数字1的编码则为06H(0000 0110B),其余的数字编码见
表1-5。缺点是当数码管的数量多时,占用单片机I/O端口接线过多,因此有了动态的显示电路。
表1-5
七段数码管显示代码表

续表

3.动态显示
动态显示电路是将多个数码管的8根数据线(a~g和dp)分别连接在一起,每个公共端作为使能引脚,以4位的共阴极电路为例,如图1-27所示。

图1-27 四位七段数码管单片机直接驱动电路(亮度有限)
动态显示原理是将要显示的数字的编码送到数码管8根公共的总线上,如果只要第一个数码管显示,则使其公共端为低电平,其余三个公共端为高电平。在显示四个不同的数字时,将需显示的数字编码送到总线上,并使其相应的数码管的公共端为低电平,其余三个高电平关闭显示,依次让第一到第四个显示不同的数字并快速切换刷新。每个数码管显示的时间控制在16ms以内,由于人眼的迟滞效应会同时看到4个数码管的数字。
4.驱动电路
七段数码管的驱动电路主要有3种:①单片机引脚加上拉电阻驱动,用于数码管功率较小时;②使用三极管或逻辑门芯片驱动,用于数码管的功率较大时;③使用专用的可编程数码管控制芯片,通常可以驱动较大功率的数码管,且占用单片机的I/O口数量少。以共阴极数码管为例:
使用第一种驱动电路的接法如图1-27所示。其中P0口已加设了2kΩ的上拉电阻,
将P0口的P0.0~P0.7分别接a~g和dp,4个公共使能端与P2.3~P2.0连接。
将P2.3配置为低电平时,电流从P0口通过第1个数码管的8个LED流回P2.3引脚,8个LED都点亮时,P2.3引脚约吸纳10~15mA电流,如果电流超过了P2口引脚电流吸纳的极限值20mA,可采用第二种驱动电路,使用三极管或门电路来增加驱动电流,共阳极的四位七段数码管连接图见图1-28所示。

图1-28 共阳极四位七段数码管三极管驱动连接
这种方式在数码管点亮时,电流从UCC开始依次经三极管、数码管内发光二极管、限流电阻后回到GND,若采用S9012三极管集射极电流最大可达500mA。与第1种电路不同的是,单片机的使能控制引脚不是直接与数码管的公共端相连,而是接到三极管的基极。
第3种驱动电路采用集成化的串行控制数码管驱动芯片。例如MAX7219,它可驱动8个七段数码管64个LED灯,内部具有寄存器可配置数码管亮度、位数及编码方式等信息,具体用法可参考MAX7219的使用说明。
二、编写程序实现数码管控制
实验板上的数码管驱动电路是采用单片机加上拉电阻直接驱动的,其电路如图1-27所示。P0口每个引脚增设了2kΩ的上拉电阻以增加驱动电流,P0.0~P0.7分别与a~g、dp连接,4个公共使能端与P2.3~P2.0连接。假如我们要显示“1234”这个数字,对应第1个数码管显示1字样,则在P0口输出数字1的编码06H:
79.MOV P0,06H
;
再在第一个数码管的控制引脚P2.3输出低电平使能显示,并保证控制引脚P2.0~P2.2输出高电平关闭其他三个数码管(为保证输出有效,首先得给P2口写入1),然后调用延时程序(不超过16ms):

根据上面的步骤写出四位七段数码管的程序段,并依次让4个数码管循环显示:

只要将上面代码放在主程序中一直循环执行即可看到数码管显示“1234”的字样。从上面的代码我们可以知道,要显示某个数字或字母时都得去查它的编码,很麻烦。这里可以用查表法来改进,先将每个数字的编码使用DB指令依次存放ROM中:

TAB为指令的标签,因为DB是伪指令,因此TAB代表的不是DB指令的地址,而是DB指令第1个参数(也就是数据)的ROM地址,第3行是数码管编码对应的字符,第4行是对应的编号。在程序中可先将TAB的值赋予DPTR,再用MOVC A,@A+DPTR指令从ROM中读取数据,然后送到P0口锁存器中:

上面的指令就是一个查表过程,从A中的值查到其相应的编码,使用查表法改进的程序如下:


在新建的“闪烁灯.ASM”文件中输入上面的程序,编译后下载到实验板中,然后单片机复位开始运行,就可以看到四位七段数码管显示“4321”。有兴趣的读者可以尝试每隔1s自动加1的程序编写。
拓展知识
一、汇编语言移位指令
移位指令能对累加器ACC中的内容进行循环移位操作,8051指令系统中支持循环左移、循环右移、带进位循环左移和带进位循环右移共4条移位指令。
◆ RL A
功能:循环左移,将累加器A中的每个位向左移动一位,最高位移到最低位。
例如:RL A
执行前,(A)=7FH,即01111111执行后,(A)=FEH,即11111110
另:二进制数中,每一个位的权为2n,因此在没溢出的前提下每向左移一位,相当于将该数乘以2。而右移恰好相反,相当于是除以2的运算。
◆ RR A
功能:循环右移,将累加器A中的每个位向右移动一位,最低位移到最高位。
例如:RR A
执行前,(A)=7FH,即01111111执行后,(A)=BFH,即10111111◆ RLCA
功能:带进位循环左移,将累加器A中的每个位向左移动一位,最高位移到进位标志C中,C的内容补到最低位。
例如:RLC A
执行前,(A)=7FH,即01111111,C=0执行后,(A)=FEH,即11111110,C=0◆ RRCA
功能:带进位循环右移,将累加器A中的每个位向右移动一位,最低位移到进位标志C中,C的内容送到最高位。
例如:RRC A
执行前,(A)=7FH,即01111111,C=0执行后,(A)=3FH,即00111111,C=1
二、汇编语言算术运算指令
功能:将源操作数与目标操作数进行加、减、乘、除等运算,其结果存放于目标操作数中。8051的逻辑单元只能对8位无符号数进行运算,利用带进位的指令时可以对多字节的无符号整数进行运算。同时利用溢出标志位,可以对有符号数进行运算。算术运算指令除加减1指令外,运算结束都会刷新PSW寄存器的标志位。算术运算指令共有24条,可分为6类。
1.加减1指令
用于循环计数和地址的偏置查表。加1指令助记符为INC(increase),减1指令助记符为DEC(decrease),只有1个目标操作数,可以是直接寻址、工作寄存器、间接寻址和累加器。加减1指令说明见表1-6。
表1-6
加减1指令说明

注意:加减1指令的执行结果不影响任何标志位。2.加法指令
将源操作数与目标操作数相加,结果存放于目标操作数中。目标寄存器只能为A,源操作数的寻址方式可以是立即数、直接寻址、工作寄存器或间接寻址。加法指令有带进位与非带进位的指令两大类,非进位的加法指令助记符为ADD,带进位的加法指令助记符为ADDC。加法指令说明见表1-7。
表1-7
加法指令说明

加法运算指令的运算结果会影响C、AC和OV标志位。当最高位bit7产生进位时,C被置位,否则复位;当低4位产生进位,即bit3位有进位时,AC被置位,否则复位;当运算结果不在有符号数范围内时,即有符号数运算溢出,OV被置位,否则复位。
3.减法指令(带进位)
减法指令都是带进位的指令,指令助记符为SUBB,目标操作数只能为A,源操作数可以是立即数、直接寻址、间接寻址和工作寄存器。运算过程是将A寄存器的内容减去源操作数及进位标志C的内容,结果存回A中。减法指令运算结果会影响C、AC与OV标志位。减法指令说明见表1-8。
表1-8
减法指令说明

当运算过程最高位产生借位时,C=1,否则C=0;当第4位产生借位时,AC=1,否则AC=0;当单字节有符号数运算溢出时,OV位置1,否则为0。
4.乘法指令
◆ MUL AB
功能:将A寄存器与B寄存器中的无符号数相乘,乘积结果的高8位赋给B寄存器,低8位赋给A寄存器。当乘积的值大于FFH时,OV标志位置1,如果OV标志位为0则说明乘积小于FFH,可在A寄存器中读取结果即可。
例如:MUL AB
执行前,(A)=20H,(B)=12H执行后,(A)=40H,(B)=02H
5.除法指令
◆ DIV AB
功能:将A寄存器中的无符号数除以B寄存器中的无符号数,所得的商存于累加器A中,余数存于B寄存器中。除法指令总是使OV和C标志位为0,如OV=1,表示B的值为0,除法有溢出,运算结果为不定值。
例如:DIV AB
执行前,(A)=20H,(B)=12H执行后,(A)=01H,(B)=0EH
6.BCD码调整指令
◆ DA A
功能:将A寄存器中的BCD码和进行进位调整。DA指令调整的依据是,如果低4位的值大于9,则加06H,并向高4位进位,如高4位的值大于9,也加06H,那么进位
标志CY置1。38
例如:DA A
执行前,(A)=ABH,(C)=0执行后,(A)=11H,(C)=1
三、汇编语言逻辑运算指令
逻辑运算指令是对操作数按位进行与、或、非、取反、异或运算的指令,它的运算结果不会影响标志位,共有4类19条逻辑运算指令。
1.逻辑与指令
功能:将两个操作数对应的位进行与运算并存回目标操作数中,当两个位都为逻辑1时,运算结果方为1,否则为0。指令助记符ANL为AND(与)和LOGIC(逻辑)的缩写,共有6条。指令说明见表1-9。
表1-9
逻辑与指令说明

例如:ANL23H,#E9H
执行前,(23H)=67H,即67H(01100111B)和E9H(11101001B)作逻辑与运算执行后,(23H)=61H
2.逻辑或指令
功能:将两个操作数对应的位进行或运算并存回目标操作数中,当两个位为逻辑0时,运算结果方为0,否则为1。指令助记符ORL为OR(或)和LOGIC(逻辑)的缩写,共有6条。指令说明见表1-10。
表1-10
逻辑或指令说明

例如:ORL A,69H
执行前,(A)=C3H,(69H)=38H,即C3H(1100 0011B)和38H(0011 1000B)作逻辑或运算,结果为1111 1011B
执行后,(A)=FBH,(69H)=38H 3.异或指令XOR
功能:将两个操作数对应的位进行异或运算并存回目标操作数中,当两个位逻辑值相反,即其中一个为真,另一个为假时运算结果方为1,否则为0。操作助记符XRL为EX
CLUSIVE OR LOGIC的缩写,共有6条指令。指令说明见表1-11。
表1-11
异或指令说明

例如:XRL A,37H
执行前,(A)=D3H,(37H)=58H,即58H(0101 1000B)和D3H(1101 0011B)作异或运算,结果为1000 1011B(8BH)
执行后,(A)=8BH,(37H)=58H
4.累加器取反指令
◆ CPL A
功能:将累加器中的内容按位取反,然后存回A中。指令只有1个目标操作数A。
例如:CPL A
执行前,(A)=3DH执行后,(A)=C2H
四、汇编语言程序结构
默认情况下程序是从0000H地址开始存放的,而ROM地址0003H~0023H的范围是单片机中断的向量地址,也就是在中断使能情况下的目标地址,因此这个区间是存储中断服务程序的,如果将用户主程序存放在这就与之相冲突了,因此在程序中使用ORG伪指令指定程序段放置的起始地址。用ORG伪指令指定在0000H~0002H存放LJMP指令,再由LJMP指令跳转到同样由ORG伪指令指定的存放主程序段的地址(一般为0030H),避开中断向量区间。通常程序开始部分用于参数初始化,如堆栈、中断等,处理完初始化程序后进入主程序开始循环执行。
我们还会经常碰到需要反复多次执行某个程序段的情况,如果重复编写这个程序段会使程序变得冗长而杂乱,因此使用子程序的结构来避免,这样能使程序的结构更加清晰,方便阅读与维护。另外程序中还经常会使用宏伪指令EQU用于代替变量地址或使用频率较高的常量,宏定义段一般位于程序最开始。下面我们来看一段程序。

如要修改上面程序中P1和P2的输出只需修改第一行的宏即可。汇编程序典型结构
如图1-29所示。

图1-29 汇编程序典型结构
能力检测
编程实现数码管静态显示秒表的倒计时。