元件说明
数码管介绍
LED数码管是一种简单、廉价的显示器,是由多个发光二极管封装在一起组成“8”字型的器件。
开发板上的数码管相关元件:
查询开发板原理图:
一位数码管引脚定义
右上为共阴极连接,右下为共阳极连接。3和8引脚表示共阴极或共阳极。
一位数码管上共有8个LED,正好与1字节相对应,并且51单片机也是8位单片机,这为我们操作数码管提供了很大便利。
图中从左到右的ABCDEFGDP是顺序的。而引脚编号却是乱序的,这是因为各个LED取就近的引脚来连接。通常使用ABCDEFGDP顺序来操作数码管。
例如,如果希望数码管显示数字6,则需要点亮ACDEFG。
对于共阴极连接,首先在共阴极接地,称为位选(相当于此位的开关,不位选的话这一位就不会亮。如果有多个数码管就需要位选希望显示的数码管)。之后在下方的电路中进行段选,依次输入10111110(称为段码)即可。
对于共阳极连接,在共阳极接入VCC(位选)。之后输入段码01000001(对应ABCDEFGDP,称为段选)即可。
四位数码管引脚定义
右上为共阴极连接,右下为共阳极连接。共阴极和共阳极单独引出(图中的12,9,8,6)。
需要哪个位显示就位选哪个位。段选方式与之前一样,不过不同位的相同段都连接在一起。
这种连接方式不能同时控制4位数码管显示4个不同的数字,因为各个段选端都接在一起。即使让它们同时亮,显示的内容也是一样的。为了使四位数码管各个位显示不同内容,通常会快速地交替显示各个位,利用人眼的余晖效应来达到同时显示不同内容的效果(动态数码管显示)。
例如,要让第三个数码管显示1,其他数码管不亮。对于共阴极连接,位选8,然后段选01100000即可。
138译码器 74HC138
74HC138,有时也会使用74LC138。
上述两个芯片在使用上基本没有区别,中间的字母表示电压、功耗上的差异。他们都属于较为古老的74系列。
主要用于通过3个引脚控制8个引脚,节省单片机IO口。此处用于数码管的位选。
引脚介绍
左上ABC为控制引脚,接在单片机IO口上。
右侧为输出引脚,接在2个4位数码管的8个共阴极端。引脚上方的横线表示低电平有效。
上下分别为VCC,GND。
左下为使能引脚。此处要使芯片工作,需要对G1输入1,对G2A和G2B输入0。
使用方法
3个输入端,每个有0和1两种状态,可以看做3位二进制数(C为最高位,A为最低位),能表示十进制0~7的8种状态,刚好就对应了右侧的8个输出端。
因为低电平有效,通过输入端选中的引脚会输出0,其余引脚输出1。因此被选中的引脚就可以位选共阴极数码管。同一时间只能有1个输出引脚有效。
双向数据缓冲器 74HC245
用于放大信号,增强驱动能力。单片机高电平驱动能力有限,而使用此芯片可以使用芯片外接电源来驱动,因此单片机只需提供控制信号。此处用于增强单片机驱动能力以进行段选。
引脚介绍
右下角输入电源VCC,GND。有时需要给VCC、GND之间加电容来进行电源滤波。
左下角OE(低电平有效)应该写作CE(Chip Enable 芯片使能),给其低电平就可以让芯片工作。
左下角DIR(Direction)控制信号方向,高电平从左到右,低电平从右到左。
左侧A接单片机,右侧B接数码管进行段选。
静态数码管显示
实现在第三个数码管上显示6。
在位选处,通过38译码器选择第三个数码管。
在段选处,从A到DP依次为1011 1110。注意在控制一整个寄存器输出时,由于高低位是反的,所以需要反着输出至P0,即0111 1101(0x7D)。
#include <REGX52.H>
void main()
{
//位选,使38译码器选中Y5 -> LED6
P2_4 = 1;
P2_3 = 0;
P2_2 = 1;
//段选,输出6的段码
P0 = 0x7D;
while(1);
}
将控制数码管的代码函数化:
//0~9的段码
int nums[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
void Nixie(char location, char num) //参数:显示位置和要显示的数字
{
//位选
location = 7 - location;
P2_2 = (location >> 0) % 2;
P2_3 = (location >> 1) % 2;
P2_4 = (location >> 2) % 2;
//段选
P0 = nums[num];
}
将代码函数化,进一步优化程序:
#include <REGX52.H>
//0~9的段码
int nums[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
void Nixie(char location, char num) //参数:显示位置和要显示的数字
{
//位选
location = 7 - location;
P2_2 = (location >> 0) % 2;
P2_3 = (location >> 1) % 2;
P2_4 = (location >> 2) % 2;
//段选
P0 = nums[num];
}
void main()
{
Nixie(2, 6);
while(1);
}
效果:
动态数码管显示
目前的电路在同一时间只能在一位显示内容,因此我们控制单片机对其快速地扫描,利用人眼的余晖效应达到同时显示的效果。
while(1)
{
Nixie(0, 1);
Nixie(1, 2);
Nixie(2, 3);
}
但是按照上述思路,如果扫描速度太快会出现残影现象(显示123的图样):
原因是程序反复重复“位选-段选-位选-段选……”操作。但是在“段选-位选”时,选择完下一位,但上一位的段选数据还存在,所以会短暂地显示在下一位的位置上“窜位”。
解决方法是在每次位选之前将段选数据清零。
#include <REGX52.H>
#include <INTRINS.H>
void Delay(int xms) //@11.0592MHz延时xms
{
unsigned char i, j;
while(xms--)
{
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
//0~9的段码
int nums[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
void Nixie(char location, char num)
{
location = 7 - location;
P2_2 = (location >> 0) % 2;
P2_3 = (location >> 1) % 2;
P2_4 = (location >> 2) % 2;
P0 = nums[num];
Delay(1); //清零前使其稳定显示1ms
P0 = 0x00; //清零
}
void main()
{
while(1)
{
Nixie(0, 1);
Nixie(1, 2);
Nixie(2, 3);
}
}
效果:
数码管的其他驱动方式
-
使用单片机直接扫描数码管,硬件设备简单,但会耗费大量的单片机CPU时间。
74HC595(需要单片机直接扫描,但可以通过3根数据线控制8个数码管):
-
而一些专用驱动芯片,内部自带显存、扫描电路,单片机只需告诉它显示什么即可。
TM1640(可控制16个数码管):
Comments NOTHING