动态显示这一块还不是理解的很透彻,先写写自己简单的想法吧,希望大家可能给点建议,尤其是延迟函数这块。
1:动态显示和静态显示的区别:
数码管分为“位选”和“段选”两个部分,先“位选”再“段选”。
当选择一个位时,段选就决定该位置显示什么内容;
当选择多个位时,段选则决定这多个位置同时显示什么内容。
以下图为例,为数码管的其中一块,有四个数字,com1~com4决定了选择这4个数字中的哪一个,而abcdefg dp则决定显示什么内容,但是不是每个数字都对应有abcdefg dp这些端口,而是这四个数字共用abcdefg dp这些端口,因此,理论上,不可能出现不同位置同时显示不同字符的情况,比如,当悬着com1和com2时,段选显示“6”(abcdefg dp控制)第一和第二个数字将会同时显示6。
要想实现不同位置同时显示不同字符的情况,有两种方法:
1.静态显示:给每个数字都各自搭配abcdefg dp端口。(缺点:端口多,成本高)
2.动态显示:仍然用上图所示的数码管结构,理论上来说不仅可能实现,但是实际情况下由于人肉眼的视觉延时等作用,依次轮流的点亮多个位置的数字,(在此过程中可让每个位置的数字显示不同的内容)人的肉眼看起来就是不同位置同时显示了不同字符的情况。简单说,编写代码流程时,就直接按依次点亮正常的位选和段选就行了,可以实现多位不同显示的情况。
简单来说:
在不改变数码管结构的情况下,静态显示就是要么多个位置同时显示一样的数字,要么就是只选择一个位置变化不同字符,动态显示就是能够实现不同位置看起来同时不同字符的情况。
2. 数码管显示的延时问题
单片机工作流程是位选 -> 段选 ->位选 -> 段选 ->位选 -> 段选 ->位选 -> 段选 ... 完成段选后,单片机就会显示新的内容,单片机的操作是需要时间的,当第一组位选段选完成后,直接进行第二组位选段选的话,前面提到的人肉眼的视觉延时和单片机余晖作用,上一组显示的内容还没完全褪去,下一组新的内容就来了,这就会导致内容重叠,为了避免这种情况,常常每一组位选段选 完成后,都会加一个延时函数来“消影”,即延长一点时间让单片机不进行其他操作,给足时间让数码管上一组的余晖慢慢消失掉,这样就不会下一组的内容重叠。
感觉理解的不太到位,欢迎大佬指正交流。
3. 实践
相关器件结构回顾在数码管静态显示篇就写过了,这里不再赘述。
3.1 任务
3.2思路
按照动态显示的原理,就是依次点亮每一个位置即可,0~3位置分别显示2018,4~5位置显示“--”,6~7位置1~12依次变化。
先从最初状态开始,1~4位置分别显示2018,5~6位置显示“--”,7~8位置01。
为了代码可读性,可以设计一个函数来表示数码管的位选和段选,后续使用时传进相应位置和内容即可,如:2018显示,可读性就很强了。
并且要进行消影,一组位选段选 后就进行Delay。
7~8位置1~12依次变化,先将1~12分为12个静态过程,则1~12可以这样表示:月份的十位g_month / 12, 月份的个位为 g_month % 12(对12取余数)
现在怎么让1~12动起来?可用一个循环和对月份累加来进行操作,月份显示的话,设置一个变量g_month,让其从1开始,然后累加,当其>12, 让g_month 重新变回1。
所以需要一个循环和if判断(是否>12),这里老师的思路是:
主要是这个延时函数的变化,第一个延时函数什么都不做,就是消耗时间,第二个延时函数就是循环t次,每一次运行函数ShowSMG,我的理解就是这里要6~7位置仅从1~12的变化时,0~5位置还是不变化的,此前我们提到能够动态的原因时因为肉眼的延迟,如果只是单纯的Delay的话,就会延迟到了一定时间,而0~5位置的某些地方肉眼看起来会消失,所以要延迟让整个位置一直在运行?(哎这里不是太理解,大神救救!!!!)
3.3 完整代码如下:
#include "stc15f2k60s2.h"
unsigned int g_month = 1;
void Delay(unsigned char t)
{
while(t--);
}
code unsigned char SMG_Table[] =
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0x88, //A
0x83, //b
0xc6, //C
0xa1, //d
0x86, //E
0x8e, //F
0xbf //-
};
void selectHC138(unsigned int n)
{
switch(n)
{
case 0:
P2 = (P2 & 0x1f) | 0x00; break;
case 1:
P2 = (P2 & 0x1f) | 0x20; break;
case 2:
P2 = (P2 & 0x1f) | 0x40; break;
case 3:
P2 = (P2 & 0x1f) | 0x60; break;
case 4:
P2 = (P2 & 0x1f) | 0x80; break;
case 5:
P2 = (P2 & 0x1f) | 0xa0; break;
case 6:
P2 = (P2 & 0x1f) | 0xc0; break;
case 7:
P2 = (P2 & 0x1f) | 0xe0; break;
}
}
void selectSMG(unsigned char position, unsigned char number)
{
selectHC138(6); // position
P0 = 0x01 << position; // position start from zero
selectHC138(7); // content
P0 = SMG_Table[number];
}
void ShowSMG()
{
//2018
selectSMG(0,2);
Delay(500); //xiao ying
selectSMG(1,0);
Delay(500);
selectSMG(2,1);
Delay(500);
selectSMG(3,8);
Delay(500);
// --
selectSMG(4,16);
Delay(500);
selectSMG(5,16);
Delay(500);
// month
selectSMG(6,g_month/10);
Delay(500);
selectSMG(7,g_month%10);
Delay(500);
}
void Delay_SMG(unsigned char t)
{
while(t--)
{
ShowSMG();
}
}
void close()
{
selectHC138(5);
P0 = 0x00;
selectHC138(4);
P0 = 0xff;
}
void main()
{
close();
while(1)
{
ShowSMG();
g_month++;
if(g_month>12)
{
g_month=1;
}
Delay_SMG(500);
}
}
欢迎指正