51 数码管
数码管:数码管是一种简单、廉价的显示器,是由多个发光二极管封装在一起组成“8”字型的器件
STC89C52RC开发板上的数码管
数码管引脚定义
一位数码管
图源:B站:江协科技 视频截图
上图为共阴极连接,下图为共阳极连接(即连接3或8都可),控制高低电平的0和1即为段码
四位一体数码管
图源:B站:江协科技 视频截图
在同一时刻只能有一个数码管被使用,即使有多个,也显示相同数字(有利于减少利用的引脚,只引出12个就可以操作32个二极管)
动态数码管显示是利用视觉暂留和数码管显示的余晖,通过快速扫描来实现
*STC89C52RC开发板上的数码管示意图(图源:普中科技参考手册)
该数码管为共阴极数码管(COM为公共端)
上面的LED接的是138译码器的输出端
数码管模块前后及内部还有以下较为重要的部件
74HC138
可以通过3个IO口(ABC)控制8个端口,其中C为高位,A为低位
下面的G1等为使能端(G1需要高电平,G2需要低电平),根据图示,通电即工作
译码器工作原理:
将3为二进制数字转换成10进制,使对应的端口(0~7)为低电平
P24为高位,读数从P22开始读(P22为最低位)
图源:普中科技参考手册
STC89C52RC开发板上的74HC138
74HC245
由模块示意图可知,模块的开头接有74HC245芯片
74HC245芯片为双向数据缓冲器:用于数据缓冲(A1-B0,A1-B1,以此类推)
OE也相当于使能端,接地工作
图源:普中科技参考手册
STC89C52RC开发板上的74HC245
DIR控制数据传递的方向(用跳线帽控制方向,接高电平VCC为从左向右,低电平为从右到左)
目的:单片机输出的最大电流有限,高电平驱动能力弱(灯会很暗),低电平驱动能力强
即单片机输出的电平就相当于一个信号,实际驱动二极管的为芯片自己的电源
STC89C52RC开发板上的跳线帽
其中P07为高位(即端口高位对应数据高位),读数从P00开始读
限流电阻
两个四位一体的排阻(也可以是8个独立的电阻),防止电流过大
图源:普中科技参考手册
STC89C52RC开发板上的限流电阻
数码管的显示
基础显示
在阴极(P2)选中需要显示数据的数码管,在阳极(P0)输入需要显示的数据
由模块图可知,我们需要在COM端设置需要显示的数码管低电平,在74HC245端向需要显示的数码管上对应的发光二极管输入高电平
(虽然各个数码管同一位置的二极管共用阳极,但此时由于其它的数码管的COM端仍旧为高电平,所以不会亮起)
输入需要显示的数据即为根据数码管的各个引脚对应的部分“画”出需要显示的数据
例:在第4位数码管显示数据,需要给 LED5 低电平,即P24 = 1;P23 = 0;P22 = 0 (二进制100 = 十进制4,即对应LED5)
(这里的P24可以时P2_4或P24,具体要看头文件的定义)
显示数据为4,则需要使abcdef均亮,则需要使P0 = 0x3F (0011 1111)
#include<STC89C5xRC.H>
void main()
{
P2_4 = 1;
P2_3 = 0;
//此时LED3、4亮起(引脚冲突)
P2_2 = 0;
//控制74HC138
P0 = 0x3F;
//控制74HC245
//第四个数码管显示0
while(1)
{
}
}
通过数组和函数改造基础代码
通过创建相应的数组和函数,我们可以以函数调用的方式快速改变数码管的显示
有关C语言的知识可见作者专栏
下面这段代码为创建一个包含显示0~9的对应代码的数组以及一个含有控制数码管显示位置的switch语句的函数
向函数传入显示位置和显示数据,可方便地改变数码管的显示状态
#include<STC89C5xRC.H>
unsigned char NixieTable[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
//0, 1, 2, 3, 4, 5, 6, 7, 8, 9对应的段码
void NixieTube_Display(unsigned char location, unsigned char num)
//分别传入显示位置、显示数字
//位置为从左向右1~8
{
switch(location)
{
case 1:
//最左边的数码管对应LED8
P2_4 = 1;
P2_3 = 1;
P2_2 = 1;
break;
case 2:
P2_4 = 1;
P2_3 = 1;
P2_2 = 0;
break;
case 3:
P2_4 = 1;
P2_3 = 0;
P2_2 = 1;
break;
case 4:
P2_4 = 1;
P2_3 = 0;
P2_2 = 0;
break;
case 5:
P2_4 = 0;
P2_3 = 1;
P2_2 = 1;
break;
case 6:
P2_4 = 0;
P2_3 = 1;
P2_2 = 0;
break;
case 7:
P2_4 = 0;
P2_3 = 0;
P2_2 = 1;
break;
case 8:
P2_4 = 0;
P2_3 = 0;
P2_2 = 0;
break;
}
P0 = NixieTable[num];
}
void main()
{
NixieTube_Display(8, 9);
while(1)
{
}
}
动态数码管显示
数码管驱动方式:
单片机直接扫描:硬件设备简单,但会耗费大量的单片机CPU时间(缺点:一旦程序阻塞,没来得及扫描,会导致数码管闪烁或熄灭)
【单片机直接扫描还有另一种模式:通过外接带74HC595的模块,用三根数据线和两根电源线控制8个数码管,可以节省单片机IO口
(在开发板上的数码管需要3+8=11个IO口才能控制8个数码管)】
专用驱动芯片:单片机通过协议告诉芯片(TM1640)显示什么,芯片内部自带显存、扫描电路
(只要两根线就可以控制16个数码管显示任意数字)
数码管快速扫描的过程:位选(选择控制哪个数码管)->段选(控制显示内容)->位选 的循环
因为单片机运行速度过快,这样会造成上一位段选的数据会跑到下一次位选的位置,导致显示的数据错乱
解决方法:在下一次位选之前将上一次段选数据清零
#include<STC89C5xRC.H>
unsigned char NixieTable[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
void NixieTube_Display(unsigned char location, unsigned char num)
{
switch(location)
{
case 1:
P2_4 = 1;
P2_3 = 1;
P2_2 = 1;
break;
case 2:
P2_4 = 1;
P2_3 = 1;
P2_2 = 0;
break;
case 3:
P2_4 = 1;
P2_3 = 0;
P2_2 = 1;
break;
case 4:
P2_4 = 1;
P2_3 = 0;
P2_2 = 0;
break;
case 5:
P2_4 = 0;
P2_3 = 1;
P2_2 = 1;
break;
case 6:
P2_4 = 0;
P2_3 = 1;
P2_2 = 0;
break;
case 7:
P2_4 = 0;
P2_3 = 0;
P2_2 = 1;
break;
case 8:
P2_4 = 0;
P2_3 = 0;
P2_2 = 0;
break;
}
P0 = NixieTable[num];
Delay(1);
//让数码管稳定显示,否则亮度会变低
//这里作者已将延时1ms的函数写入头文件,向函数传递的数字x即为延时x ms
P0 = 0x00;
//清零
}
void main()
{
NixieTube_Display(8, 0);
while(1)
{
NixieTube_Display(1, 1);
//Delay(500);
NixieTube_Display(2, 2);
//Delay(500);
NixieTube_Display(3, 3);
//Delay(500);
//让数码管同时显示多个数字实际上就是数码管在不断扫描,可以通过延时函数来体现
}
}