基于单片机的数码管实验 八段数码管简介

描述

8.1 八段数码管简介

在我们生活中随处可见数码管的应用,数码管的应用形式多种多样,抛开事物表象,深入到它的本质,正所谓万变不离其中,数码管应用的原理都是基本相通的。本章我们将详细介绍数码管的基本原理以及数码管的应用。最典型的数码管为8段LED数码管,外观如下图所示:
开发板
如上图所示,数码管包括A、B、C、D、E、F、G以及DP共8段,实际上8段为8个独立的LED。上面8段LED组成1位数码管。数码管按照内部连接方法的不同分为共阴型或共阳,当8段LED的阴极连接在一起称为为共阴型,阳极连接在一起称为共阳型。如下图所示为4位共阳型的8 段数码管。
开发板
如上图所示,4位数码管每一位的8段LED的阳极连在一起,组成共阳极型数码管,8段数码管的阴极分别连接在一起。当选中某一位的阳极使其为高电平,使8段数码管的阴极对应的位低电平便可点亮数码管。例如,DP、G、F、E、D、C、B、A电平值依次为:1、1、1、1、1、0、0、1时数码管显示为数字1。据此可以编辑共阳数码管的真值表,如下表所示:
开发板
一般点亮一段数码管需要至少10mA, 而单片机管脚输出的电流较小,无法驱动数码管,可以采用上拉电阻、三极管驱动或采用专用驱动芯片进行驱动。RY-51单片机开发板采用两个74HC573驱动芯片,驱动2个4位的数码管,共8位数码管如下图所示:
开发板

8.2 锁存器74HC573功能介绍

如上图所示,U3,U4为8位的数据锁存器74HC573,D7-D0为数据输入端,Q7-Q0为与输入端一一对应的输出端。74HC573有2个控制信号分别为第1、11管脚、1管脚为芯片使能控制端,11管脚为数据锁存控制端。

当1接高电平时,芯片不工作,无论数据输入端为高、低电平,输出端Q7-Q0为高阻态。只有当1管脚为低电平时,芯片才能正常工作,如图8-3所示U3、U4均将1管脚直接接地。

在1管脚接地的情况下,当11管脚为高电平时,D7-D0输入为高电平时,Q7-Q0输出为高、同理当输入为低电平时,输出为低电平,此时相当于芯片的D7-D0与Q7-Q0是一一连通的。

当11管脚为低电平时,无论输入端D7-D0是高或者低电平,Q7-Q0保持原来的值不变。

利用上面的特点我们就可以实现数据的锁存了。假设我们要把0xFB锁存到Q7-Q0,首先使11管脚为高电平,给输入端D7-D0赋值0xFB,此时输出端Q7-Q0输出为0xFB,此时将11管脚拉为低电平并一直保持,那么此后无论输入端D7-D0为何值,Q7-Q0均为0xFB,因此完成了数据的锁存。74HC573真值表如下表所示:
开发板

如上面原理图所示,根据锁存器74HC573的特点,利用单片的一个8位端口,以及两个用于控制的I/O口便能控制8位数码管了。如图所示,输入数据D7-D0与单片的P0口相连,U3、U4的11管脚分别与单片机的I/O口P2.7、P2.6相连。锁存器U3的输出端Q7~Q0分别与数码管的a-g,DP相连,锁存器U4的输出端Q7-Q0分别与8位数码管的公共端相连。

8.3 单片机控制数码管

下面我们通过举例来讲解数码管的控制过程,以使第5位数码管显示数字8为例。如表8-1所示数字8对应数码管真值为0x80,通过单片机的P0口将0x80锁存到U3的输出口。如图8-3所示,第5位数码管公共端WE5对应的是锁存器U4的Q4,应只需Q4为高电平,Q7-Q5,Q3-Q1为低电平,便可使第5位数码管显示数字8,其它数码管不显示。因此通过单片机的P0口将0x10锁存到U4。数码管的显示总结如下,首先将字码锁存到U3,然后将数码管的显示位锁存到U4。数码管显示程序如下所示:

/*----------------------------------------------------
** 数码管5显示数字8
----------------------------------------------------*/
#include< reg52.h >

sbit DU = P2^7;
sbit WE = P2^6;

void main()
{
	P0 = 0x80;//显示数字8
	DU = 1;
	DU = 0;

	P0 = 0x10;//第5位数码管
	WE = 1;
	WE = 0;

	while(1);
}

程序代码如上所示,在主程序中首先把数字8锁存到锁存器U3,然后将数码管5公共端的高电平锁存到U4,将程序编译并下载到单片机检验实际显示效果。每一个数字对应数码管都是固定的,在实际应用中每条语句中都对P0进行赋值的话会比较繁琐而且不便于程序阅读,我们往往将数码管的真值放在一个数组中,程序中调用数组即可,改进程序如下所示:

/*----------------------------------------------------
** 数码管5显示数字8,字码组放入数组中
----------------------------------------------------*/
#include< reg52.h >

#define uchar  unsigned char
#define uint unsigned int

sbit DU = P2^7;
sbit WE = P2^6;

//共阳型(0~9,A,b,C,d,E,F,全亮,全灭),字码组
uchar code table_D[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0x00,0xFF};
//位选数组
uchar code table_W[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0xFF,0x00};

void main()
{
	
	P0 = table_D[8];//显示数字8
	DU = 1;
	DU = 0;

	P0 = table_W[4];//第5位数码管
	WE = 1;
	WE = 0;

	while(1);
}

如代码所示,将数码管真值表放入数组table_D[],数组的第0位对应的数字为0,第8位对应的数字为8,因此,如代码所示,需要显示数字8,直接将table_D[8],赋值给P0即可,方便又好记。Table_W[]设计的原理相同。将程序下载到开发板,显示效果与前面保持一致。

前面讲解的都是让某一个数码管显示某一个固定的值,下面我们讲解较为复杂一点数码管显示。例如,第1位数码管显示数字0,500ms之后第2位数码管显示数字1,直到第8位数码管显示7,然后循环上述步骤。要实现上面的功能我们需要用到前面讲解的定时器功能,即每500ms在定时器中断程序中给数码管更新一次数值。程序代码如下所示。

/*----------------------------------------------------
** 数码管1~8循环显示数字0~7,间隔500ms
** 定时器中断方式
----------------------------------------------------*/
#include< reg52.h >

#define uchar  unsigned char
#define uint unsigned int

#define FOSC 11059200 //单片机晶振频率
#define T_1ms (65536 - FOSC/12/1000)  //定时器初始值计算

uint count = 0;
uint flag  = 0;

sbit DU = P2^7;
sbit WE = P2^6;
//共阳型(0~9,A,b,C,d,E,F,全亮,全灭),字码组
uchar code table_D[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0x00,0xFF};
//位选数组
uchar code table_W[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0xFF,0x00};
void main()
{
	TMOD = 0x01;	 //定时器工作模式配置
	TL0  = T_1ms;	//装载初始值
	TH0  = T_1ms > >8;

	TR0  = 1;		 //启动定时器
	ET0  = 1;		 //允许定时器中断
	EA   = 1;		 //开总中断

	while(1);	  //循环
}

void timer0() interrupt 1
{
	TL0 = T_1ms;//重装初始值
	TH0 = T_1ms > >8;

	count++;
	if(count >= 500)//每一毫秒进入一次中断,达到500次则为500ms,跟新一次数码管显示。
	{
		count = 0;

		P0 = table_D[flag];//数字0~7循环
		DU = 1;
		DU = 0;
	
		P0 = table_W[flag];//数码管1~8循环点亮
		WE = 1;
		WE = 0;

		flag++;
		if(flag >=8)
			flag =0;
	}
}

将程序下载到单片机开发板检验效果是否与预期一致。

8.4动态显示数码管

前面讲解的数码管显示均为在某个时间内只能显示一个数码管,那么如何让8个数码管同时显示不同的数。前面我们讲解的例子为数码管1到8分别显示数字1到8,显示的间隔时间为500ms,如果我们将时间间隔该为100ms,那么数码管切换的速度比以前快了5倍,当把间隔该为2ms时,由于间隔时间太短,感觉前一个数码管还没来的及完全熄灭,后面的数码管就点亮了,这就是人眼睛的视觉暂留效应。

因此,你可以看到数码管上同时显示了01234567共八个数,这就是动态数码管显示的原理。只需要将上面的程序稍加改动便可实现,将语句“if(count>=500)”改为“if(count>=2)”。将修改好的程序编译下载到开发板观察效果。

8.5 数码管消隐

当把上面的程序下载到开发板时,8位数码管会同时显示“01234567”共8个数字。但是,细心的同学会发现,有的数码管不应该显示的段会有点亮,但亮度会比较低,看起来像阴影一样。这种现象是怎么形成的呢,又该怎么消除呢?下面我们通过程序来具体分析。
开发板

8.4节所讲的定时器中断程序如上图所示,根据前面介绍可知,每隔2ms语句51-59会执行一次,每次flag的值会加1。第一次时flag=0,数码管1显示数字0,第二次时,flag=1,数码管2显示数字1,如此循环下去。当第二次执行到第51行语句时,此时还没有选择数码管2,而是第一次执行语句57时选中了的数码管1,只有当语句执行到57时,才完成数码管2的选定,因此,在执行语句51-57期间,是数码管1显示了数字1,当执行到57之后的2ms时间内是数码管2显示了数字1。由于语句执行语句51-57的时间远小于2m,因此亮度较低,这就是我们上面观察到的阴影。阴影产生的原因找到了,下面我们讲解阴影的消除了。如果我们在语句51之前先把所有的数码关都关掉,就不会出现上述情况了。程序如下:

void timer0() interrupt 1
{
	TL0 = T_1ms;//重装初始值
	TH0 = T_1ms > >8;

	count++;
	if(count  >= 2)//每一毫秒进入一次中断,达到2次则为2ms更新一次数码管。
	{
		count = 0;

		P0 =table_W[9];//关闭所有数码管,消隐处理
		WE = 1;
		WE = 0;

		P0 = table_D[flag];//数字0~7循环
		DU = 1;
		DU = 0;
	
		P0 = table_W[flag];//数码管1~8循环点亮
		WE = 1;
		WE = 0;

		flag++;
		if(flag  >=8)
			flag =0;
	}
}

将程序重新编译,下载到开发板。正如程序设计所愿,数码管阴影成功被消除。

8.6 数码管应用

这里我们在扩展一下数码管的应用,做一个简单秒表,在数码管上显示。程序设计原理如下:在定时器中断程序中增加一个变量T_count,当1ms进入一次定时器中断时自加一次,然后在主程序中判断是否达到了1000次即1s的时间,每秒钟变量Sec自加1次,记录时间。将sec个、十、百、千位保存到数组Buf_LED[]中,在将数组显示到数码管上,程序如下所示:

/*----------------------------------------------------
** 秒表
----------------------------------------------------*/
#include< reg52.h >

#define uchar  unsigned char
#define uint unsigned int

#define FOSC 11059200 //单片机晶振频率
#define T_1ms (65536 - FOSC/12/1000)  //定时器初始值计算

uint count = 0;
uint flag  = 0;

uint T_count  = 0;
uint Sec   = 0;

sbit DU = P2^7;
sbit WE = P2^6;	

uchar  Buf_LED[8] ={0};


//共阳型(0~9,A,b,C,d,E,F,全亮,全灭),字码组
uchar code table_D[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0x00,0xFF};
//位选数组
uchar code table_W[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0xFF,0x00};

void main()
{
	TMOD = 0x01;	 //定时器工作模式配置
	TL0  = T_1ms;	//装载初始值
	TH0  = T_1ms > >8;

	TR0  = 1;		 //启动定时器
	ET0  = 1;		 //允许定时器中断
	EA   = 1;		 //开总中断

	while(1)	  //循环
	{
		if(T_count >=1000)
		{
			T_count =0;
			Sec++;
		
		Buf_LED[7]= Sec%10;
		Buf_LED[6]= Sec/10%10;
		Buf_LED[5]= Sec/100%10;
		Buf_LED[4]= Sec/1000%10;
		}
	}
}

void timer0() interrupt 1
{
	TL0 = T_1ms;//重装初始值
	TH0 = T_1ms > >8;
	
	T_count++;
	count++;
	if(count >= 2)//每一毫秒进入一次中断,达到2次则为2ms更新一次数码管。
	{
		count = 0;

		P0 =table_W[9];//关闭所有数码管,消隐处理
		WE = 1;
		WE = 0;

		P0 = table_D[Buf_LED[flag]];//显示秒
		DU = 1;
		DU = 0;
	
		P0 = table_W[flag];//数码管1~8循环点亮
		WE = 1;
		WE = 0;

		flag++;
		if(flag >=8)
			flag =0;
	}
}

8.7本章小结

本章详细介绍了数码管的工作原理、锁存器74HC573的工作原理及使用。数码管的显示控制以数码管显示中的定时器应用。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分