【51单片机】数码管(原理图 + 程序实例)

学习使用的开发板:STC89C52RC/LE52RC
编程软件:Keil5
烧录软件:stc-isp

开发板实图:
在这里插入图片描述

数码管介绍

数码管是在开发板左上角的8位数字
在这里插入图片描述
数码管在实际生活也很常见,像是电子闹钟,电子测温计,我们平常见到的红灯倒计时其实也是由许许多多数码管形成的
在这里插入图片描述


引脚接线图

数码管的显示其实是分成很多部分的,下图的 A ~ G 和 DP(小数点)每个都需要单独控制亮灭
在这里插入图片描述

在引脚接线图中,数码管有两种接法:
在这里插入图片描述

  • 共阴极:引脚置 1 灯亮
  • 共阳极:引脚置 0 灯亮

上述是单个数码管的引脚接线,开发板中的数码管是四个一体,引脚接线如下:
在这里插入图片描述
图中采用共阳极接线,共用下面的8根接线,减少接线数,也可以做到互补影响。例如:如果12为0,则无论下面8根线是否为0,都不会亮;反之如果12为1,则下面8根线为0的,相应的部分就会亮起


原理图

STC89C52STC89C52RC/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:决定显示什么数字
  1. 首先,LED串口P2_2 ~ P2_438译码器 决定,逻辑如下。注意从左往右依次是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;
	}
  1. 接下来是显示的数字,我们可以借由上述提供的数组
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)
	{}
}

效果如下:
在这里插入图片描述


以上就是本篇博客的所有内容,感谢你的阅读
如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值