【51单片机系列】数码管使用
本文是关于数码管的使用介绍。数码管根据显示方式分为静态数码管和动态数码管。
一、静态数码管
1.1 显示器介绍
单片机系统中常用的显示器有:
- 发光二极管LED显示器,Light Emitting Diode;
- 液晶LCD显示器,Liquid Crystal Display;
- TFT液晶显示器等
发光二极管LED显示器有两种显示结构:段显示(7段,米字型等)和点阵显示(5x8、8x8点阵等)。这一节是关于段显示的LED显示器。
同LED类似,段显LED数码管根据LED的不同接法可以分为2类:共阴和共阳。
如下左图是段显示LED数码管的各个LED段,中间的图片是共阴极接法,a-f为高电平时,对应的LED就会亮;右图是共阳极接法,a-f为低电平时,对应的LED段会亮。
使用LED显示器时,需要注意这两种接法。为了显示数字或字符,必须对数字或字符进行编码。
七段数码管加上一个小数点,共计8段,因为为LED显示器提供的编码正好是一个字节。
根据电路连接图显示16进制数的编码如下:
1.2 静态数码管显示原理
LED显示器工作方式有两种:静态显示方式和动态显示方式。
静态显示的特点是每个数码管的段选必须接一个8位的数据线来保持显示的字形码。当送入一次字形码后,显示字形可一直保持,直到送入新的字形码为止。
这种方法的有点是占用CPU时间少,显示便于监测和控制。缺点是硬件电路比较复杂,成本较高。
1.3 静态数码管仿真
如下是共阴极LED数码管proteus仿真电路。
其中用到了74HC573芯片,该芯片起到锁存器的作用,其管脚如下:
OE为使能端,当OE为低电平时,锁存器开始工作,所以给OE接地;
VCC和GND为电源和地端,仿真时不显示该两个管脚;
LE为锁存端,当LE为高电平时,O0 - O7跟D0 - D7状态一样,当LE为低电平时,O0 - O7锁存数据,无论D0 - D7怎么变化,O0 - O7都保持锁存之前的那个状态。这里给LE接电源。
数码管显示数字0,代码实现如下:
仿真结果:
二、动态数码管
当需要显示多位字符时,静态数码管就不合适了,此时要选择数码管的动态显示
2.1 多位数码管介绍
多位数码管,即是两个或两个以上单个数码管并列集中在一起形成一体的数码管。当多位一体时,他们内部的公共端是独立的,负责显示什么数字的段选全部是连接在一起的。独立的公共端可以控制多位一体中的哪一位数码管点亮,而连接在一起的段选线可以控制这个能点亮的数码管显示什么字符。
通常把公共端叫做位选线,连接在一起的段线叫做段选线。有了这两个线,通过单片机及外部驱动电路就可以控制任意的数码管显示任意的数字了。
如下是proteus中的一种共阴极四位一体数码管,其中A-G、DP就是段选线,这些线控制数码管显示什么字符;右边的1-4是位选线,这些线控制这4个数码管哪一个显示字符。
2.2 数码管动态显示原理
动态显示的特点是将所有数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。
点亮数码管采用动态扫描显示。所谓的动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时在显示。
动态显示的亮度比静态显示要差一些,所以在选择限流电阻时应略小于静态显示电路中的。
动态显示,就是利用减少段选线,分开位选线,利用位选线不同时选择通道,改变段选数据来实现的。
比如在第一次选中第一位数码管时,给段选数据0,下一次选中第二位数码管时显示1。为了在显示1的时候,0不会小时,必须在人肉眼观察不到的时间里再次点亮第一次点亮的0。
需要了解的是,人的肉眼正常情况下只能分辨变化超过24ms间隔的运动。也就是说,在下一次点亮0的时间差不得大于24ms。这时会发现,数码管点亮是在向右或者向左一位一位点亮的,形成了动态效果。
2.3 74HC245和74HC138芯片介绍
如果只使用单片机IO口驱动数码管是不可行的,这里就需要增加外部驱动芯片,这里介绍一种驱动芯片74HC245。
2个4位一体的共阴数码管的位选线有8根,直接让单片机IO口控制是没有问题的,但考虑到51单片机IO口资源的限制,通常会使用一种IO扩展芯片,只需要很少的单片机IO口就可以扩展出8个控制口,通过级联方式甚至可扩展出更多的控制口。这里介绍一种IO扩展芯片74HC138,只需要单片机3个IO口就可以实现8个位选管脚的控制,大大节省了芯片的IO资源。
2.3.1 74HC245芯片介绍
74HC245是一种三态输出、八路信号收发器,主要应用与大屏显示,以及其它的消费类电子产品中增加驱动。
74HC245芯片主要特性:
- 采用CMOS工艺
- 宽电压工作范围:3.0V - 5.0V
- 双向三态输出
- 八线双向收发器
- 封装形式:SOP20、SOP20-2、TSSOP20、DIP20
74HC245芯片管脚定义及功能如下
管脚定义
A0 - A7是数据输入/输出管脚;B0 - B7是数据输入/输出管脚;OE输出使能管脚,OE=1时处于高阻态;DIR方向控制管脚,DIR=1,A->B,DIR=0,B->A;GND逻辑地管脚;VDD逻辑电源管脚;
管脚真值表如下:
输出使能OE | 输出控制DIR | 工作状态 |
---|---|---|
L | L | B输入A输出 |
L | H | A输入B输出 |
H | X | 高阻态 |
从管脚功能定义说明及真值表可以知道,给OE使能管脚低电平,DIR管脚为高电平,传输方向是A->B;给OE低电平,DIR为低电平,传输方向是B->A。输出端的状态取决于输入端,输入为低电平,输出即为低电平,输入为高电平,输出即为高电平。
如果OE管脚为高电平,输出为高阻态。
通常使用74HC245芯片用作驱动只会让其在一个方向输出,即DIR管脚为高电平,传输方向为A->B。
2.3.2 74HC138芯片介绍
74HC138芯片是一种三通道输入、八通道输出译码器,主要应用于消费类电子产品。
74HC138芯片主要特性
- 采用CMOS工艺
- 低功耗
- 工作电压:3.0V - 5.0V
- 封装形式:SOP16
74HC138管脚定义及功能
Y0 - Y7是数据输出管脚;A0 - A2是数据输入管脚;E1 - E3 是使能控制管脚。
使能控制管脚及数据输入管脚真值表如下
输入 | 输入 | 输入 | 输入 | 输入 | 输入 | 输出 | 输出 | 输出 | 输出 | 输出 | 输出 | 输出 | 输出 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
E1 | E2 | E3 | A2 | A1 | A0 | Y7 | Y6 | Y5 | Y4 | Y3 | Y2 | Y1 | Y0 |
H | X | X | X | X | X | H | H | H | H | H | H | H | H |
X | H | X | X | X | X | H | H | H | H | H | H | H | H |
X | X | L | X | X | X | H | H | H | H | H | H | H | H |
L | L | H | L | L | L | H | H | H | H | H | H | H | L |
L | L | H | L | L | H | H | H | H | H | H | H | L | H |
L | L | H | L | H | L | H | H | H | H | H | L | H | H |
L | L | H | L | H | H | H | H | H | H | L | H | H | H |
L | L | H | H | L | L | H | H | H | L | H | H | H | H |
L | L | H | H | L | H | H | H | L | H | H | H | H | H |
L | L | H | H | H | L | H | L | H | H | H | H | H | H |
L | L | H | H | H | H | L | H | H | H | H | H | H | H |
从管脚功能定义及真值表可以知道,给E1、E2使能管脚低电平,E3管脚为高电平,哪个管脚输出有效电平(低电平),看A0,A1,A2输入管脚的电平状态。如果A0,A1,A2都为低电平,则Y0输出有效电平(低电平),其它管脚都输出高电平。
使能管脚E1、E2任意一个为高电平或E3为低电平,不论输入是什么,输出都是高电平。
简单的方法就是,A0、A1、A2输入相当于3个2进制数,A0是低位,A1是次高位,A2是高位,Y0-Y7具体哪一个输出有效电平,看输入二进制对应的十进制数值。比如输入是101(A2,A1,A0),其对应的十进制是5,Y5输出有效电平(低电平)。
2.4 动态数码管仿真
使用proteus仿真2个四位一体的共阴极数码管,设计如下
使用74HC245芯片连接2个四位一体数码管的段选端,74HC138扩展IO口,使用P2口的P22、P23、P24控制输入,输出控制2个四位一体数码管的位选端。
设计软件实现从左到右显示0-7。代码如下:
/*
实现功能:2个四位一体数码管从左到右依次显示0~7
[2023-12-05] zoya
*/
#include "reg52.h"
typedef unsigned char u8;
typedef unsigned short u16;
sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;
// 共阴极LED数码管编码表
u8 code smg[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, // 0 ~ 5
0x7d, 0x07, 0x7f, 0x67, // 6 ~ 9
0x77, 0x7c, 0x39, 0x5e, 0x78, 0x71, 0x00 }; // a ~ f 不显示
// 延时函数,i=1延时10us
void delay(u16 i)
{
while(i--);
}
// 数码管显示函数
void digDisplay()
{
u8 i;
for(i=0;i<8;i++)
{
switch(i)
{
case 0: LSA = 0; LSB = 0; LSC = 0; break; // 000 Y0
case 1: LSA = 1; LSB = 0; LSC = 0; break; // 001 Y1
case 2: LSA = 0; LSB = 1; LSC = 0; break; // 010 Y2
case 3: LSA = 1; LSB = 1; LSC = 0; break; // 011 Y3
case 4: LSA = 0; LSB = 0; LSC = 1; break; // 100 Y4
case 5: LSA = 1; LSB = 0; LSC = 1; break; // 101 Y5
case 6: LSA = 0; LSB = 1; LSC = 1; break; // 110 Y6
case 7: LSA = 1; LSB = 1; LSC = 1; break; // 111 Y7
}
P0 = smg[i];
delay(100);
P0 = 0x00;
}
}
void main()
{
u8 i;
LSA=0;
LSB=0;
LSC=0;
P0 = 0x00;
while(1)
{
digDisplay();
}
}
仿真结果: