相信在单片机入门中,学会点亮数码管是必备的知识,书本上也有详细介绍了使用的方法,然而,在实际的应用中,单片机的代码不仅只有数码管,同时也应会有定时器,I/O口控制等代码,增加代码后数码管的显示就不会变得那么简单,往往会出现最后一位的数码管比其他位的数码管要亮(HC595驱动,动态扫描方式,不讨论其他),下面就让我们来解决这个问题。
一:引起原因
这里先说明原本的数码管代码经过调试可用,排除其他原因(不亮,乱码不讨论),看下面的代码(部分):
if( ((cout==2)&&(pw<=100)&&(pw>=0)) || ((mov==1)&&(cout==0)) )
{
Dis_buf[0]=29;
Dis_buf[1]=pw/100%10;
if(Dis_buf[1]==0) Dis_buf[1]=26;
Dis_buf[2]=pw/10%10;
Dis_buf[3]=pw/1%10;
if(regGroup[0]==1) {Dis_buf[0]=32;}
}
else if(pw>100)
{
Dis_buf[0]=29;
Dis_buf[1]=30;
Dis_buf[2]=30;
Dis_buf[3]=30;
if(regGroup[0]==1) {Dis_buf[0]=32;}
}
Output_595();//这是数码管显示函数
原因:程序执行到Output_595()后,此时数码管应选到最后一位导通,其他位不亮(具体原理参照595驱动方法)。之后程序应继续往下执行或循环,再次到达if代码段时,要计算数值,消耗一定时间,导致程序延迟进入Output_595(),使得最后一位数码管导通时间,比其他位导通时间要长一点,所以会更亮。
//数码管控制码
BYTE code SEG7[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//0-9的显示控制码,共阳
BYTE code Scan_bit[]={0x08,0x04,0x02,0x01};
//4位数码管,有且只有一个亮
BYTE Dis_buf[]={0,0,0,0,0}; //显示缓冲区
...
....
.....
//数码管显示函数
void Output_595()
{
BYTE i;
for(i=0;i<4;i++)
{
Input_595(SEG7[Dis_buf[i]]);//显示字符数据
Input_595(Scan_bit[i]);//第i位亮
P_HC595_RCLK=1;
P_HC595_RCLK=0;
Delay595(1);
}
//退出for循环后,此时应为Scan_bit[3],程序继续往下执行,第4位数码管始终选通
}
二:解决方法
1)既然从上述知道,最后一位数码管较亮,是程序有一定的延时引起的,在程序中添加延时的方法也不可取。那么我们可以换位思考一下,其他位的数码管亮度是一样的,说明导通时间一样,只要让最后一位导通时间也一样,就可以解决问题了。
2)添加一位数码管:
例如我这里的硬件用的是4位数码管,那么我就用5段数码管的显示程序,即使第5位数码管还是会比其他位要亮,但有什么关系呢?我的硬件实际只有4位数码管,第5位数码管是没有的,但是前面4位数码管亮度都是一样的,这样把第4位数码管更亮的问题转移到不存在的第5位数码管(程序里面有,实际上没有),就可以解决问题了。
BYTE code Scan_bit[]={0x08,0x04,0x02,0x01,0x00}; //5个数码管,显示字符方法同样没变,只需用前面4位,第5位是要用来承担亮度较亮的一位
...
....
for(i=0;i<5;i++)
{
Input_595(SEG7[Dis_buf[i]]);
Input_595(Scan_bit[i]);
P_HC595_RCLK=1;
P_HC595_RCLK=0;
Delay595(1);
}
3)同样,硬件是8位的数码管,在程序中虚拟添加多一位数码管,就可以解决第8位数码管更亮的问题,但要注意的是,按照HC595驱动、动态扫描方式,到第8位数码管亮的时候,传送的数据应是0x01,前面7位数码管应当是灭的状态,接下来应该传送第9位数码管的数据,前面8位数码管应当是灭的状态,但这里一个字节只有8bit控制,所以传送的数据只有0x00才符合要求。
BYTE code Scan_bit[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,0x00};
...
....
for(i=0;i<9;i++)
{
Input_595(SEG7[Dis_buf[i]]);
Input_595(Scan_bit[i]);
P_HC595_RCLK=1;
P_HC595_RCLK=0;
Delay595(1);
}
4)注释
1.Scan_bit[]是数码管位选码,即控制其中一个数码管亮/灭。
2.typedef unsigned char BYTE;
3.本例中使用共阳极数码管。