学习使用的开发板:STC89C52RC/LE52RC
编程软件:Keil5
烧录软件:stc-isp
开发板实图:
数码管介绍
数码管是在开发板左上角的8位数字
数码管在实际生活也很常见,像是电子闹钟,电子测温计,我们平常见到的红灯倒计时其实也是由许许多多数码管形成的
引脚接线图
数码管的显示其实是分成很多部分的,下图的 A ~ G 和 DP(小数点)
每个都需要单独控制亮灭
在引脚接线图中,数码管有两种接法:
- 共阴极:引脚置 1 灯亮
- 共阳极:引脚置 0 灯亮
上述是单个数码管的引脚接线,开发板中的数码管是四个一体,引脚接线如下:
图中采用共阳极接线,共用下面的8根接线,减少接线数,也可以做到互补影响。例如:如果12为0,则无论下面8根线是否为0,都不会亮;反之如果12为1,则下面8根线为0的,相应的部分就会亮起
原理图
STC89C52
和 STC89C52RC/LE52RC
都是采用 共阴极
接线
如图 a ~ g 和 dp 都有对应的引脚编号,连接到74HC245
,通过P0串口
控制
例如,我们想在数码管显示2,我们需要知道有哪些部分需要亮起
如图,有A(P0_0),B(P0_1),D(P0_3),E(P0_4),G(P0_6)
则设置P0 = 0101 1011,即0x5B
读者可以自行尝试推导一下各个数字所对应的P0值,博主直接提供对应值,读者可以比对一下,也方便后续直接使用
常用数码管对应值数组
unsigned char NixieTubeNums[] = {0x3F, 0x06, 0x5B, 0x4F,0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
LED1 ~ LED8 的控制通过38译码器
控制
因为3位二进制数,刚好表示 0 ~ 7,共8种情况
图中,P24为高位,P22为低位。
例如P24 = 0, P23 = 0, P22 = 1,即001,表示1,对应Y1,即LED2为0,LED2对应从左往右第7个数码管
一次只能让一个数码管亮起
因为只有LED2为0,后续改变P0,只会让LED2数码管亮
编程练习
指定位置显示指定数字
我们可以将该方法封装成一个函数,方便后续使用
参数有两个:第一个location
指定哪个位置显示,第二个num
指定显示的数字
没有返回值
void lightNixieTube(unsigned char location, unsigned char num);
逻辑如下
一个数码管是否亮起,主要取决于两部分,LED串口(P2_2 ~ P2_4)
和 P0
LED串口
:决定哪个位置的数码管可以显示P0
:决定显示什么数字
- 首先,
LED串口
由P2_2 ~ P2_4
经38译码器
决定,逻辑如下。注意从左往右依次是LED8 ~ LED1
//第一个位置是LED8,对应38译码器111
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 = NixieTubeNums[num];
这样就完成了,完整代码如下:
unsigned char NixieTubeNums[] = {0x3F, 0x06, 0x5B, 0x4F,0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
//显示指定位置指定数字
void lightNixieTube(unsigned char location, unsigned char num)
{
//第一个位置是LED8,对应38译码器111
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 = NixieTubeNums[num];
}
测试一下:
void main()
{
lightNixieTube(1, 2);
while(1)
{}
}
显示多个数字 —— 消影
虽然一次只能控制一个数码管显示,但是因为人感知时间相比于机器是很慢的,如果以很快的速度,分别显示不同的数码管,那么在我们看来,就是同时显示了多个数字
我们尝试如下代码:
unsigned char NixieTubeNums[] = {0x3F, 0x06, 0x5B, 0x4F,0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
//显示指定位置指定数字
void lightNixieTube(unsigned char location, unsigned char num)
{
//第一个位置是LED8,对应38译码器111
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 = NixieTubeNums[num];
}
//显示多个
void showNums()
{
while(1)
{
lightNixieTube(1, 1);
lightNixieTube(2, 2);
lightNixieTube(3, 3);
}
}
void main()
{
showNums();
while(1)
{}
}
我们想要在123位置分别显示123,效果如下:
隐约可以看到,123显示出来了,但是出现了类似 “重影” 的效果,原因如下:
我们理想的情况是,每个数码管的显示是独立的,但是在我们完成第一次数码管的显示后,要更改P22 ~ P24,此时P0是有数据的,更改P22 ~ P24后会出现预料外的显示
比如,我们第一个数是1位置的1,然后更改P22 ~ P24为2位置,此时就会变成在2位置显示一个1,所以出现了重影的效果
知道了原因后,我们其实只要在一次显示后,清空P0即可,但注意不要立即清空,会让显示的亮度变低
然后再显示不同位置之间我们也需要等待一下,太快的改变仍会造成“重影”
这个过程我们叫作 —— 消影
更改后的代码如下:
#include <REGX52.H>
#include <stdio.h>
unsigned char NixieTubeNums[] = {0x3F, 0x06, 0x5B, 0x4F,0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
//等待指定毫秒数
void Delayms(unsigned int xms) //@12.000MHz
{
while(xms--)
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
//显示指定位置指定数字
void lightNixieTube(unsigned char location, unsigned char num)
{
//第一个位置是LED8,对应38译码器111
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 = NixieTubeNums[num];
Delayms(1);
P0 = 0x00;//消影
}
//ÏÔʾ¶à¸ö£¬Ê¹Óö¯Ì¬É¨Ãè
void showNums()
{
while(1)
{
lightNixieTube(1, 1);
Delayms(20);//消影
lightNixieTube(2, 2);
Delayms(20);//消影
lightNixieTube(3, 3);
Delayms(20);//消影
}
}
void main()
{
showNums();
while(1)
{}
}
效果如下:
以上就是本篇博客的所有内容,感谢你的阅读
如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。