#太原理工大学机器人团队#51单片机20天学习打卡——Day6

数码管的消隐

#include
sbit ADDR0=P1^0;
sbit ADDR1=P1^1;
sbit ADDR2=P1^2;
sbit ADDR3=P1^3;
sbit ENLED=P1^4;
unsigned char code Led Char[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};
void main()
{
unsigned char i=0;          //动态扫描的索引
unsinged int cnt=0;         //记录T0中断次数
unsigned long sec=0;        //记录经过的秒数
unsigned char LedBuff[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}       //数码管显示缓冲区
ENLED=0;
ADDR3=1;                    //因为需要动态改变数码管的位选,所以ADDR0~2不需要初始化了
TMOD=0x01;
TH0=0xFC;                   //定时1ms
TL0=0x67;
TR0=1;
while(1)
{
if(TF0==1)
{
TF0=0;
TH0=0xFC;                   
TL0=0x67;
cnt++;
if(cnt>=1000)
{
cnt=0;
sec++;
//以下代码将sec按十进制从低到高依次提取并转为数码管显示字符
LedBuff[0]=LedChar[sec%10];
LedBuff[1]=LedChar[sec/10%10];
LedBuff[2]=LedChar[sec/100%10];
LedBuff[3]=LedChar[sec/1000%10];
LedBuff[4]=LedChar[sec/10000%10];
LedBuff[5]=LedChar[sec/100000%10];
}
//以下代码王城数码管的动态扫描刷新
switch(i)
{
case 0:ADDR2=0;ADDR1=0;ADDR0=0;i++;P0=LedBuff[0];break;
case 1:ADDR2=0;ADDR1=0;ADDR0=1;i++;P0=LedBuff[1];break;
case 2:ADDR2=0;ADDR1=1;ADDR0=0;i++;P0=LedBuff[2];break;
case 3:ADDR2=0;ADDR1=1;ADDR0=1;i++;P0=LedBuff[3];break;
case 4:ADDR2=1;ADDR1=0;ADDR0=0;i++;P0=LedBuff[4];break;
case 5:ADDR2=1;ADDR1=0;ADDR0=1;i=0;P0=LedBuff[5];break;
drfault:break;
}
}
}
}

上图是一个数码管动态扫描的程序代码。

事实上,这个数码管动态显示程序的运行效果并不完美,仔细看就会发现,数码管不该亮的段,似乎有微微的发亮,这种现象叫做”鬼影“。

解决这种问题的方法有两种,其一是延时,延时之后肉眼就看不到“鬼影”了,但延时时一种非常拙劣的手段,且不说延时多久能看到”鬼影“,延时后,数码管亮度会普遍降低。

在说第二种方法之前,我们先了解一下“鬼影”产生的原因(结合上述代码进行说明)。

在进行数码管切换时,比如从case 5切换到case 0的时候,case 5的位选用的是“ADDR0=1;ADDR1=0;ADDR2=1;"假如此刻case 5也就是最高位数码管对应的值是0,要切换成case 0的数码管位选是”ADDR0=0;ADDR1=0;ADDR2=0;“而对应的数码管的值假如是1,又因为C语言程序是一句一句顺序往下执行的,每一条语句的执行都会占用一定空间,即使这个时间非常非常短暂,但是当把”ADDR0=1"改变成“ADDR0=0"的时候,这个瞬间存在了一个中间状态ADDR0=0;ADDR1=0;ADDR2=1;在这个瞬间,就给case 4对应的数码管DS5瞬间赋值了0。当全部写完了ADDR0=0;ADDR1=0;ADDR2=0;后,这个时候,P0还没有正式赋值,而P0此刻却保持了前一次的值,也就是这个瞬间上,就给case 4对应的数码管DS1赋值了一个0,直到把case 0后边的语句全部完成后,刷新才正式完成。而在这个刷新过程种,有两个错误的赋值,虽然量的时间很短,但还是能够发现。

为了避免这种错误的赋值,我们可以采用以下方法:

(1)关闭段:在switch(1)这句程序之前,加一句P0=0xFF,这样就把数码管所有的段都关闭了,当把”ADDR"的值全部搞定后再给P0赋对应的值。

(2)关闭位:在switch(i)这句程序程序之前,加上一句ENLED=1;等到把ADDR2=0;ADDR1=0;ADDR0=0;I++;P0=LedBuff【0】;这几条刷新程序全部写完后,在加上以句ENLED=0;然后再进行break操作。

你可能感兴趣的:(#太原理工大学机器人团队#51单片机20天学习打卡——Day6)