【51单片机】(三)数码管(原理,静态、动态显示)


一.数码管基础知识

四位一体数码管:
【51单片机】(三)数码管(原理,静态、动态显示)_第1张图片
数码管电路原理:
【51单片机】(三)数码管(原理,静态、动态显示)_第2张图片
与之有关的元件——“138译码器”:
【51单片机】(三)数码管(原理,静态、动态显示)_第3张图片
①想要点亮一个数码管并让其显示数字,我们需要操作两个端口,给两个端口不同的电平。我们的单片机数码管上端是共阴极的,所以发光的条件是上端赋予低电平,下端赋予高电平
【通俗理解:上方LED端口选择要点亮哪一个数码管;下方abcdefg端口确定点亮什么数字。】

(1)数码管上方有8个接口LED1~8,分别对应接到“译码器”的右输出端。译码器的左端连接单片机的3个P2口。(具体如何用三个P2口控制8个LED输出口,后面会单独讲解)
(2)每一体数码管下方引出abcdefg和dp共八个接口,分别对应点亮一个LED长条(图中有标注)或是小数点,点亮几个就可以组合成一个数字。这八个接口接到74HC245缓冲器的右输出端,而74HC245的左端连接单片机的8个P0口。74HC245左右端一一对应(A0-B0,A1-B1……)。
(缓冲器是用来提高单片机驱动能力的一个元件,VCC可以增强信号强度)

比如我现在想让LED6数码管发出“3”的数字。那么,上方接口所赋予的电平情况应该是(从左往右)1101 1111;下方接口接通abcdg,应该是(从左往右)1111 0010。但是,

我们在缓冲器左端传入的二进制必须从高位往低位读取。

比如,现在从左往右端口是1111 0010,但是P0输入端输入的是0100 1111,也就是P0=0x4F。
【51单片机】(三)数码管(原理,静态、动态显示)_第4张图片 【51单片机】(三)数码管(原理,静态、动态显示)_第5张图片
为了方便,这里总结数码管段码表:
【51单片机】(三)数码管(原理,静态、动态显示)_第6张图片

数码管静态显示时,只能让其中一个数码管发光。也就是说,在同一时间,上端接口只能保证有一个输入0。(具体原因见“译码器”工作方法)

译码器工作方法:

左端输入端输入的信号按CBA排序,组成一个三位的二进制数,再将这个二进制数转化为十进制数,这个十进制数对应右端输出端的下标,这个输出端将会输出低电平。

比如输入:A : 0 、B : 1 、C : 1,排序为110,转十进制为6,Y6口(对应LED7)将会输出低电平,其他端口均输出高电平。


二.数码管静态显示

根据之前的讲解,不难写出代码了:
这个代码可以让数码管LED3显示数字“3”。

#include
void main()
{
	    P2_4=0; P2_3=1; P2_2=0; //CBA:010
		P0=0x4F;  //OUTPUT 3:abcdg -> 1111 0010 -> 0100 1111 -> 0x4F
		while(1)
		{
		}
}

为了方便操作,我们将数码管每一个位置的数字显示封装在函数中。
①首先,使用段码表,初始化一个数组NixieTable,后面可以直接调用,显示数字。
②其次用分支语句写出所有数码光发光的情况。(P2端口)

void Nixie(int LED,int number)   
{
		char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00}
		switch(LED)   //CBA
		{	
			case 1: P2_4=0; P2_3=0; P2_2=0; break;
			case 2: P2_4=0; P2_3=0; P2_2=1; break;
			case 3: P2_4=0; P2_3=1; P2_2=0; break;
			case 4: P2_4=0; P2_3=1; P2_2=1; break;
			case 5: P2_4=1; P2_3=0; P2_2=0; break;
			case 6: P2_4=1; P2_3=0; P2_2=1; break;
			case 7: P2_4=1; P2_3=1; P2_2=0; break;
			case 8: P2_4=1; P2_3=1; P2_2=1; break;
		}
		
		P0=NixieTable[number];
}

当然,我们可以把函数改的人性化一些。内部LED1~8序号是从右往左的,我们在写函数的时候,可以反一反。


三.数码管动态显示

由于数码管在同一时间只能静态显示一个数字,那么如果我们让多个数字同时显示,该怎么办呢?

我们可以让这些LED按顺序以极高的频率快速闪烁,在人眼看来就是同时显示。

有了这样的方法,我们先付诸实践:(略去函数部分)

void main()
{
		while(1)
		{
			   Nixie(1,1);
			   Nixie(2,2);
			   Nixie(3,3);
		}
}

但是,实际上的效果却是:虽然显示了321,但是每个数字不该点亮的灯条会有一些模糊的光泛出:
【51单片机】(三)数码管(原理,静态、动态显示)_第7张图片
这显然是不符合我们的预期的。原因是单片机在操作“段选->位选”的时候,速度很快,可能会篡位,导致顺序错乱。

于是,我们在数码管动态显示时,还必须完成一步“消影”操作。

在Nixie函数中,每一次“位选->段选”操作完,在极短的时间之内,完成将P0清零(P0=0x00;)的操作。

void Nixie(int LED,int number)   
{
		char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00};
		switch (LED)   //CBA
		{	
			case 1: P2_4=0; P2_3=0; P2_2=0; break;
			case 2: P2_4=0; P2_3=0; P2_2=1; break;
			case 3: P2_4=0; P2_3=1; P2_2=0; break;
			case 4: P2_4=0; P2_3=1; P2_2=1; break;
			case 5: P2_4=1; P2_3=0; P2_2=0; break;
			case 6: P2_4=1; P2_3=0; P2_2=1; break;
			case 7: P2_4=1; P2_3=1; P2_2=0; break;
			case 8: P2_4=1; P2_3=1; P2_2=1; break;
		}
		
		P0=NixieTable[number];
		Delay(100);   //<----------------------
		P0=0x00;     //<-----------------------
}

这样执行之后,就不会出现残影了。
【51单片机】(三)数码管(原理,静态、动态显示)_第8张图片

你可能感兴趣的:(51单片机笔记,单片机)