一、数码管的显示原理
数码管:是一种可以显示数字和其他信息的电子设备,可以看成是多个二极管的组成。
数码管有单位数码管、双位数码管、四位数码管,我们开发板上的数码管为2个四位数码管。
数码管显示原理:通过点亮内部的发光二极管来发光
引脚:又被称为管脚,从集成电路内部电路引出与外围电路的接线,所有的引脚构成了这块芯片的接口
单位数码管的引脚有10个,内部一共有8个小的发光二级管,还有2个引脚是公共端,其实只有一个公共端,但是生产厂家为了封装统一,把这2个引脚连接在了一起。
数码管根据其公共端所接的阳极和阴极的不同,分为了共阴极数码管和共阳极数码管。
共阳极接法:几个二极管的阳极接在一起,接到VCC(高电平),我们要想点亮,只要在在对应的二极管的阴极接上低电平即可。
共阴极接法:几个二极管的阴极接在一起,接到GND(低电平),我们要想点亮,只要在在对应的二极管的阳极接上高电平即可。
我们所用开发板上的是数码管是共阴极接法,如果要要显示数字1,我们只需让“b、c”得高电平,其余引脚给低电平即可,转换为16进制表示即为0x06,下面为共阴极数码码表:
16进制表示 | 显示的数字 |
---|---|
0x3f | 0 |
0x06 | 1 |
0x5b | 2 |
0x4f | 3 |
0x66 | 4 |
0x6d | 5 |
0x7d | 6 |
0x07 | 7 |
0x7f | 8 |
0x6f | 9 |
16进制表示 | 显示的字母 |
---|---|
0x77 | A |
0x7c | B |
0x39 | C |
0x5e | D |
0x79 | E |
0x71 | F |
0x76 | H |
0x38 | L |
0x40 | - |
0x00 | 熄灭 |
STC89C52开发板上所用的是2个四位的数码管,在其内部公共端是独立的,独立的公共端可以用来控制哪一位数码管点亮,段线是连接在一起的,用来负责显示什么数字,我们常常把公共端叫做”位选线“,连接在一起的线叫做”段选线“。
位选:控制哪一个数码管亮
段选:控制数码管显示的内容
有了这两个线之后,通过单片机及外部驱动电路就可以控制任意的数码管显示任意的数字。
二、74HC573锁存器工作原理
OE:Output Enable 输出使能端
LE:Latch Enable 锁存器使能端
D0~D7:数据的输入引脚
Q0~Q7:数据的输出引脚
GND:地线接地端
VCC:供电电压
74HC573锁存器:是一种对脉冲电平敏感的存储单元电路,它们可以在特定输入脉冲电平作用下改变状态。锁存,就是把信号暂存以维持某种电平状态。锁存器的最主要作用是缓存,其次完成高速的控制器与慢速的外设的不同步问题,再其次是解决驱动的问题,最后是解决一个 I/O 口既能输出也能输入的问题。一个口可以控制两个LED灯,对第一个LED灯送数据,“打开”第一个锁存器,而“锁住”第二个锁存器,使得第二个LED上的数据不变。对第二个LED灯送数据时,“打开”第二个锁存器而“锁住”第一个锁存器,使得第一个LED灯上的数据不变。
从图中来看,简单来说就是用D引脚控制Q引脚,OE和LE影响D引脚控制Q引脚的结果。
L:低电平
H:高电平
D:数据输入端
Q:数据输出端
X:任意是任何状态:高电平或者低电平
Z:高阻态
74HC573有三种工作模式:
在实际应用中,我们往往是按照(1)OE端给上一个低电平,LE端给上一个高电平;(2)将数据从单片机的口线上输出到Dn;(3)此时给OE端一个低电平,LE端一个低电平;(4)此时我们所需要的数据就锁存在Qn上了,输入的数据再变化也不能影响到输出的数据了
三、74HC573锁存器在数码管中的应用
从图中我们可以看出,我们要驱动2片4位的数码管,也就是说驱动8位的数码管,我们采用2片的74HC573锁存器进行驱动,一片用来锁存位码,一片用来锁存段码。74HC573锁存器能够驱动几位数码管取决于使用了几片74HC573。
74HC573锁存器驱动8位数码管
四、实际静态数码管程序的设计
设计要求:我们假设需求是点亮第一个数码管,并让第一个数码管显示数字1,以下是我们实现的步骤:
程序代码:
#include //52单片机头文件
sbit WE = P2^7; //位定义 WE为标识符 代表着位选 P2^7为地址符 申明U8锁存器的锁存端
sbit DU = P2^6; //位定义 DU为标识符 代表着段选 P2^7为地址符 申明U9锁存器的锁存端
int main() //主函数
{
WE = 1; //打开U8锁存端
P0 = 0xfe; //送入位选信号 0xfe为16进制表示方法,转换为二进制为1111 1110,代表着第一个数码管被点亮
WE = 0; //关闭U8锁存端
DU = 1; //打开U9锁存端
P0 = 0x06; //送入段选信号 0x06为16进制表示方法,转换为二进制为1111 0110,代表着显示数字1
WE = 0; //关闭U9锁存端
while(1); //程序到这里停止
}
进阶显示1(联系前面所学的延时函数)
设计要求:让实验板子上的8个数码管同时点亮,依次显示数字0到F,循环下去
这里我们要引入编码定义的概念
uchar code table[] = { //这里的uchar 为unsigned char的缩写 在使用时需要先定义
0x3f 0x06 0x5b 0x4f
0x66 0x6d 0x7d 0x07
0x7f 0x6f 0x77 0x7c
0x39 0x5e 0x79 0x71};
编码定义与C语言中数组定义的方法非常类似,不同的地方在于多了一个code,code即为编码的意思。
注意:单片机C语言中定义数组时是占用内存空间的,而定义编码时是直接分配到程序空间中的,使用编码的方式进行编译,占用的是程序空间,而不是内存空间,节省了资源
[]中的当前数字个数可以加也可以不加,C51编译器在编译时能够自动计算出来,通常来说,为了方便,不用去加
调用数组的方式:
P0 = table[4];
即将table这个数组中第5个元素直接赋给P0口,即
P0 = 0x6d;
注意:在使用数组的时候,table后面中括号的数字是从0开始的,对应后面大括号里的第1个元素。
程序代码:
#include //51单片机头文件
sbit WE = P2^7; //位选信号的锁存器控制 位定义 WE为标识符 代表着位选 P2^7为地址符 申明U8锁存器的锁存端
sbit DU = P2^6; //段选信号的锁存器控制 位定义 DU为标识符 代表着段选 P2^7为地址符 申明U9锁存器的锁存端
#define uchar unsigned char //宏定义(预处理指令,不是语句,后面不用加分号)其中直接用uchar替换了unsigned char 此时我们可以用uchar num等价于unsigned char num;
#define uint unsigned int //宏定义(用法和上面类似)
uchar num; //定义变量num
uchar code table[] = { //显示0~f的码表
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void delay(uint z) //延时函数
{
unsigned int x,y;
for(x = z;x>0;x--)
for(y=144;y>0;y--);
}
void main() //主函数
{
while(1) //进入大循环
{
for(num=0;num<19;num++) //16个数循环显示
{
WE = 1; //打开U8锁存器(U8为位选)
P0 = 0x00; //送入位选信号,选中8个数码管
WE = 0; //关闭U8锁存器
delay(1000); //调用延时函数
DU = 1; //打开U9锁存器(U9为段选)
P0 = table[num]; //送入段选信号,调用数组中的值
DU = 0; //关闭U9锁存器
}
}
}
效果:(由于压缩成gif大小有限,只上传了开始和结尾的部分)
进阶显示2
设计要求:让实验板子上的数码管从第一位开始流动显示数字1
程序代码:
#include //51单片机头文件
sbit DU = P2^6; //段选信号的锁存器控制 位定义 WE为标识符 代表着位选 P2^7为地址符 申明U8锁存器的锁存端
sbit WE = P2^7; //位选信号的锁存器控制 位定义 DU为标识符 代表着段选 P2^7为地址符 申明U9锁存器的锁存端
#define uchar unsigned char //宏定义(预处理指令,不是语句,后面不用加分号)其中直接用uchar替换了unsigned char 此时我们可以用uchar num等价于unsigned char num;
#define uint unsigned int //宏定义(用法和上面类似)
unsigned char code table[]={ //数码管各位的码表
0xfe,0xfd,0xfb,0xf7,
0xef,0xdf,0xbf,0x7f};
void delay(uint z) //延时函数
{
unsigned int x,y;
for(x = z;x>0;x--)
for(y=144;y>0;y--);
}
void main()
{
uchar num;
while(1)
{
for(num=0;num<8;num++)
{
WE = 1; //打开U8锁存器(U8为位选)
P0=table[num]; //送入位选信号,调用数组
WE = 0; //关闭U8锁存器
DU = 1; //打开U9锁存器(U9为段选)
P0=0x06; //送入段选信号,显示数字1的代码
DU = 0; //关闭U9锁存器
delay(200); //调用延时函数
}
}
}
效果: