单片机学习笔记---动态数码管显示

上一节我们得出一个结论,多位一体的数码管不可能在同一时刻显示多个不同数字,即使有多位选中的话,那显示的数字也会是相同的。这是由于他们共用引脚导致的这个现象。当然这也是为了节省引脚的连接方式,方便操作。

那这样的连接方式怎样才能让数码管同时显示不同数字呢?

这就是我们要实现的第二功能:动态数码管显示。就是利用人眼视觉暂留和数码管显示的余晖这个原理来实现的。比如我们先让数码管的第一位显示“1”,然后很快地让第二位显示“2”,很快地让第三位显示“3”......然后不断地让它扫描,就是很快地扫描的“1”“2”“3”“1”“2”“3”“1”“2”“3”......这样就可以同时显示123了。

单片机学习笔记---动态数码管显示_第1张图片

这一节我们就来看看动态数码管显示的代码怎么写

新创建工程,把上一节的代码复制过来

单片机学习笔记---动态数码管显示_第2张图片

单片机学习笔记---动态数码管显示_第3张图片

多复制几段这个

单片机学习笔记---动态数码管显示_第4张图片

改成

单片机学习笔记---动态数码管显示_第5张图片

然后再加个1ms延时函数

单片机学习笔记---动态数码管显示_第6张图片

复制过来改造成这样:

然后每次显示后就延时个200ms

单片机学习笔记---动态数码管显示_第7张图片

编译无错误后看一下效果

单片机学习笔记---动态数码管显示_第8张图片

单片机学习笔记---动态数码管显示_第9张图片

单片机学习笔记---动态数码管显示_第10张图片

这时我们看到动态数码管的第一第二第三位分别显示1 2 3,而且一直在来回扫描闪烁,并且看起来还不能同时显示1 2 3。

这还不是我们想实现的效果

怎么才能让这些数字看起来是静止的1 2 3?

我们需要把延时的时间改短一点,改成20ms看看效果

单片机学习笔记---动态数码管显示_第11张图片

单片机学习笔记---动态数码管显示_第12张图片

这样我们基本能看到1 2 3三个数字同时显示了,但是还是肉眼可见地在闪烁,再把延时时间缩短成10ms

单片机学习笔记---动态数码管显示_第13张图片

这样看起来效果好多了,把延时时间所得越短,效果就越好,肉眼就越看不出数字在闪烁,就好像1 2 3三个数字是静态同时显示的一样。这勉强是我们想要达到的效果,但还不是最佳效果。

如果我们把延时代码先注释掉会出现什么情况呢?

单片机学习笔记---动态数码管显示_第14张图片

单片机学习笔记---动态数码管显示_第15张图片

这时候我们发现显示数字的位置是错乱的,3显示在了第一位数码管,2显示在了第四位数码管上。

这就是为什么我们前面不是直接让它显示三个数字,还要加个Delay慢慢来看,就是因为这个原因。

这种现象是数码管常见的问题,叫做数码管的消影(它在其他位数码管上显示的影子),为什么会出现影子呢?

首先数码管显示会有一个位选和段选。它就是位选-段选-位选-段选-位选-段选等等如此循环,但是因为单片机的速度很快,就在前一个位选段选到下一个位选和段选中间,上一位的数据就会篡到下一个数据里面去,因为他们是挨在一起的,当选中下一位的时候,上一位的数据自然就会过来,因为下一位的数据还没有到。所以就会出现显示数字篡位的问题

如果避免这个问题呢?

我们可以在下一个位选之前先把上一个段选清零。

可以在子函数中的段选结束后,加一个Delay 1ms,让它稳定地显示,因为如果立马清零的话,数码管就比较暗。然后加上P0=0x00;

单片机学习笔记---动态数码管显示_第16张图片

这里的Delay还是保持注释状态

单片机学习笔记---动态数码管显示_第17张图片

这是编译看看效果:

单片机学习笔记---动态数码管显示_第18张图片

这次的效果非常完美,没有出现篡位的现象,没有肉眼可见地闪烁。是完美地静止状态的三个数字同时显示。

完整的代码如下:

#include 

//定义数组
unsigned char NixieTable[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

void Delay(unsigned int xms)		
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

void Nixie(unsigned char location, Number)
{
	//位选
	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[Number];
	Delay(1);//延时1ms
	P0=0x00;//清零
}

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

以上就是这节想要实现的动态数码管显示的效果。

接下来总结一下额外的知识:

数码管驱动方式:

  1. 单片机直接扫描:硬件设备简单,但会耗费大量的单片机CPU时间。(也就是本节讲的这种方式)

另外以下两种模块也是通过单片机直接扫描的方式实现的。它是通过三根数据线和两根电源线就可以控制8个数码管,但是它也需要单片机扫描。

单片机学习笔记---动态数码管显示_第19张图片

  1. 专用驱动芯片(推荐):内部自带显存、扫描电路,单片机只需告诉它显示什么即可

单片机学习笔记---动态数码管显示_第20张图片

第二种方式就是只需要两根通讯线(通讯协议之后会学),只需要按照这个协议告诉它显示什么,它就自己不断地扫描数码管,而且不会出现闪烁。上图中的芯片是TM1640,只需要两根线就可以控制16位数码管显示任意数字。

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