我们用switch语句完成的情况。
#include
sbitADDR0=P1^0;
sbitADDR1=P1^1;
sbitADDR2=P1^2;
sbitADDR3=P1^3;
sbitENLED=P1^4;
unsignedcharcodeLedChar[]={//数码管显示字符转换表
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E
};
unsignedcharLedBuff[6]={//数码管显示缓冲区,初值0xFF确保启动时都不亮
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
voidmain()
{
unsignedchari=0;//动态扫描的索引
unsignedintcnt=0;//记录T0中断次数
unsignedlongsec=0;//记录经过的秒数
ENLED=0;//使能U3,选择控制数码管
ADDR3=1;//因为需要动态改变ADDR0-2的值,所以不需要再初始化了
TMOD=0x01;//设置T0为模式1
TH0=0xFC;//为T0赋初值0xFC67,定时1ms
TL0=0x67;
TR0=1;//启动T0
while(1)
{
if(TF0==1)//判断T0是否溢出
{
TF0=0;//T0溢出后,清零中断标志
TH0=0xFC;//并重新赋初值
TL0=0x67;
cnt++;//计数值自加1
if(cnt>=1000)//判断T0溢出是否达到1000次
{
cnt=0;//达到1000次后计数值清零
sec++;//秒计数自加1
//以下代码将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)
{
case0:ADDR2=0;ADDR1=0;ADDR0=0;i++;P0=LedBuff[0];break;
case1:ADDR2=0;ADDR1=0;ADDR0=1;i++;P0=LedBuff[1];break;
case2:ADDR2=0;ADDR1=1;ADDR0=0;i++;P0=LedBuff[2];break;
case3:ADDR2=0;ADDR1=1;ADDR0=1;i++;P0=LedBuff[3];break;
case4:ADDR2=1;ADDR1=0;ADDR0=0;i++;P0=LedBuff[4];break;
case5:ADDR2=1;ADDR1=0;ADDR0=1;i=0;P0=LedBuff[5];break;
default:break;
}
}
}
}
程序完成的功能是一模一样的,但大家看一下,switch语句是不是比if...else语句显得要整齐清爽呢。
1.4.2数码管显示消隐
不知道同学们是否发现了,我们的这两个数码管动态显示程序的运行效果似乎并不是那么完美,第一个小问题,大家仔细看,数码管的不应该亮的段,似乎有微微的发亮,这种现象叫做“鬼影”,这个“鬼影”严重影响了我们的视觉效果,我们该如何解决呢?
同学们在今后可能会遇到各种各样的实际问题,可能很多都是我们没有讲过的,遇到问题怎么办呢?大家要相信,你作为初学者,遇到的问题肯定不是第一个遇到的,肯定有前辈已经遇到过相同的或类似的问题,他们一般都会在网上发表各种帖子,各种讨论,所以大家遇到问题,首先就应该形成一个到网上搜索的条件反射,这个问题大家可以到网上搜:“数码管消隐”或者“数码管鬼影解决”,多找相关关键词搜索试试,会搜索也是一种能力。
大家在网上搜了一下会发现,解决这类问题的方法有两个,其中之一是延时,延时之后我们肉眼就可能看不到这个“鬼影”了。但是延时是一个非常拙劣的手段,且不说延时多久能让我们看不到“鬼影”,延时后,我们的数码管亮度会普遍降低。我们解决问题呢,不能只知其然,还要知其所以然,那么我们首先就来弄明白为什么会出现“鬼影”。
“鬼影”的出现,主要是在数码管位选和段选产生的瞬态造成的。举个简单例子,我们在数码管动态显示的那部分程序中,实际上每一个数码管点亮的持续时间是1ms的时间,1ms后进行下个数码管的切换。在进行数码管切换的时候,比如我们从case5要切换到case0的时候,case5的位选用的是ADDR0=1;ADDR1=0;ADDR2=1;假如此刻case5也就是最高位数码管对应的值是0,我们要切换成的case0的数码管位选是ADDR0=0;ADDR1=0;ADDR2=0;而对应的数码管的值假如是1。又因为C语言程序是一句一句顺序往下执行的,每一条语句的执行都会占用一定的时间,即使这个时间非常非常短暂。但是当我们把“ADDR0=1”改变成“ADDR0=0”的时候,这个瞬间存在了一个中间状态ADDR0=0;ADDR1=0;ADDR2=1;在这个瞬间上,我们就给case4对应的数码管DS5瞬间赋值了0。当我们全部写完了ADDR0=0;ADDR1=0;ADDR2=0;后,这个时候,我们的P0还没有正式赋值,而P0此刻却保持了前一次的值,也就是在这个瞬间,我们又给case0对应的数码管DS1赋值了一个0。直到我们把case0后边的语句全部完成后,我们的刷新才正式完成。而在这个刷新过程中,有2个瞬间我们给错误的数码管赋了值,虽然很弱(因为亮的时间很短),但是我们还是能够发现。
|