✨文章内容会不断优化,如果你感兴趣的话,欢迎点藏收藏关注我哟
🧨如果文章有哪里看不懂的欢迎评论区或私信留言,我会及时回复的
⏰如果文章出现错误,欢迎指正,看到后我会马上改正
文章目录
一、动态显示原理
在数码管动态显示中,工作原理主要基于视觉暂留效应。视觉暂留效应是一种生理现象,当图像快速闪烁或移动时,它在我们眼睛中留下的影像会持续留存短暂的时间,这使得我们可以看到一个连续不断的图像,而不是一系列单独的闪烁或移动的图像。
数码管动态显示具体来说是这样实现的:首先,你选中其中一个数码管(通常由硬件电路如译码器完成),并且将你想要在数码管上显示的数字或字符传送到相应的段上。然后,你迅速切换(20ms左右)到下一个数码管,并将你想要显示的内容传送到这个数码管的相应段上。这个过程在所有的数码管之间快速循环,以达到同时显示在所有数码管上的效果。每个数码管的点亮时间非常短,但由于视觉暂留效应,我们看到的效果是所有的数码管都在同时显示内容。
这种方式的优点是,尽管一次只能驱动一个数码管,但节省了大量的硬件资源。然而,缺点在于需要通过编程控制,以确保显示内容持续更新,从而创建出一种所有数码管都在持续显示的错觉。如果刷新速度过慢,我们可能会看到显示内容的闪烁。一般来说,如果刷新频率能够达到50Hz或以上,就足以避免人眼察觉到的闪烁现象。
二、动态显示的目的
2.1 单片机IO口有限
假设开发板上8个数码管都有独立的段码输入,8个数码管每个都要8个段选输入IO(a b c d e f g dp),且每一个都要有位选IO(com x),那么一共需要8*8+8=72个IO口,很明显51没有那么多IO口。如果8个数码管共用段码输入,那么只需要8+8=16个IO口,又因为段选和位选共用一个P0口,所以只需要8个IO口就能够实现段选和位选。
2.2 节省IO口资源
即使IO口够用的情况下,通常也不会采用每个数码管独立的段选信号,太浪费资源了。
2.3 节能
通过视觉暂留效应和数码管余辉效应,大脑感受不到数码管熄灭了一段时间,熄灭的这段时间就可以节省下大量的能力。
三、代码编写
动态数码管显示基于静态数码管显示,依次从左到右控制每一个数码管,每个数码光管点亮的时间大概为2ms,这样每一轮的刷新时间就是2*8=16ms,刷新频率大于50Hz,这就满足了人眼的视觉暂留效应。
👉重点知识:数码管刷新频率指的是,所有用到的数码管刷新的频率,并不是单个数码管的刷新频率!
单个数码管显示代码
void display_SMG_Bit(unsigned char dat, unsigned pos)
{
P0=0x01<<(pos-1); // 设置位选数据
selectHC573(6); // 打开位选锁存器
selectHC573(0); // 关闭位选锁存器
P0=dat; // 设置段码数据
selectHC573(7); // 开启段码锁存器
selectHC573(0); // 关闭段码锁存器
}
动态数码管显示代码
void display_D_SMG(int dat1)
{
display_SMG_Bit(dat[2],1); // 显示第一个数码
Delay2ms(); // 延时一段时间2ms左右最佳
display_SMG_Bit(dat[0],2); // 显示第二个数码
Delay(300); // 延时一段时间
display_SMG_Bit(dat[2],3); // 显示第三个数码
Delay2ms(); // 延时一段时间
display_SMG_Bit(dat[3],4);
Delay2ms();
display_SMG_Bit(dat[16],5);
Delay2ms();
display_SMG_Bit(dat[16],6);
Delay2ms();
display_SMG_Bit(dat[dat1 / 10],7);
Delay2ms();
display_SMG_Bit(dat[dat1 % 10],8);
Delay2ms();
}
四、数码管残影问题以及如何消影
📌如何解决数码管“串台”,导致数码管显示不正常,也就是如何解决消影的问题?
4.1 问题现象
看下面这张图,对比箭头所指的两个数码管,可以看到上面那个数码管有前面一个数码管的残影,而下面的就没有,这个问题的出现跟代码有关系,所以我们要注意代码的编写。
4.1 问题分析
4.3 问题解决
将上面单个数码管显示的函数修改一下:
void display_SMG_Bit(unsigned char dat, unsigned pos)
{
/*消影*/
P0=0xff; // 清空段码数据
selectHC573(7); // 打开段码锁存器
selectHC573(0); // 关闭段码锁存器
P0=0x01<<(pos-1);
selectHC573(6);
selectHC573(0);
P0=dat;
selectHC573(7);
selectHC573(0);
}
五、数码管刷新方法
5.1 软件延时实现动态数码管显示
这种方式就是利用延时函数delay来实现动态数码管的显示,比较常见,不做赘述。
5.2 定时器中断实现动态数码管显示
这种方式就是在定时器中断服务函数中刷新动态数码管,具体做法就是设置定时器中断的时间为2ms,然后每次进入中断服务函数就刷新一个数码管。
volatile unsigned char seg_pos=0; // 因为这个变量在中断中改变,所以需要添加volatile关键字修饰
void Timer0_Isr(void) interrupt 1
{
display_SMG_Bit(seg_pos,segduan[segdat[seg_pos]]);
seg_pos++;
if(seg_pos==8)
seg_pos=0;
}
void Timer0_Init(void) //1800微秒@12.000MHz 1.8ms
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xF8; //设置定时初始值
TH0 = 0xF8; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
5.3 二者有什么区别?
软件延时会阻塞程序的其他函数运行,降低实时性。
同时,如果while(1)里面有运行的比较久的函数也会影响数码管的刷新显示。
✨博客会一直改进,有新的问题或知识我都会在这里分享,欢迎大家点赞收藏关注。
✨文中如果出现什么问题,欢迎大家帮忙指正,谢谢大家!