|
发表于 2008-4-19 05:21:56
|
显示全部楼层
我做过温湿度数码管显示,反正单片机的速度足够高,找一定时器,快速扫描,保证所有数码管扫描一遍的时间在人眼不闪烁的速度(10ms以下),例如,设置一个char型计数单元,如果等于0,先把数码管的数据送出到并口,如果等于1,就第一个数码管亮,等于2的时候把数码管1关闭,同时把数码2的数据送到并口上,等于3的时候数码管2亮,以此类推. 以上程序在定时器中断中实现,变量每次累加一次. 如果变量大于某个数,就直接等于255,则下一个中断,此变量就等于0了,整个显示过程重新开始.
变量变到255的门限(就是每次加一之后,某个数值之后变为255)太小时,循环显示的周期就非常快,数码管的亮度较高,当然可以通过限流电阻控制,如果通过软件控制,就通过设置门限方法,门限越大,则亮度越暗,同时循环的周期越长,因为只有开始的几次计数,数码管亮,后续的数码管不亮,只是变量在累加,所以如果门限值太高了,会造成闪烁(当然把定时器的中断速度提高也可以解决闪烁问题),如果太低就太亮,所以调试的时候选择一个合理门限即可.参考如下.
SIGNAL(SIG_OVERFLOW2)
{
// Reinitialize Timer2's value
TCNT2 = 0xa3; // 重新赋值
// TODO: Add your code here
//sbi(PIND, 0X07);
//sbi(PINB, 0X01);
static unsigned char led_count = 0; // 显示计数变量
switch(led_count)
{
case 0: // 第一个数码管的数据准备,数据显示开始
{
wendu_test = 1;
UDR0 = DIS_DATA1;
break;
}
case 1: // 第一个数码管亮
{
cbi(PORTC, 0);
break;
}
case 2: // 第一个数码管灭,第二个数码管数据准备
{
sbi(PORTC, 0);
UDR0 = DIS_DATA2;
break;
}
case 3: // 第二个数码管亮
{
cbi(PORTC, 1);
break;
}
case 4: // 第二个数码管灭,第三个数码管数据准备
{
sbi(PORTC, 1);
UDR0 = DIS_DATA3;
break;
}
case 5: // 第三个数码管亮
{
cbi(PORTC, 2);
break;
}
case 6: // 第三个数码管灭,第四个数码管数据准备
{
sbi(PORTC, 2);
UDR0 = DIS_DATA4;
break;
}
case 7: // 第四个数码管亮
{
cbi(PORTC, 3);
break;
}
case 8: // 第四个数码管灭,数据显示完毕
{
sbi(PORTC, 3);
wendu_test = 0;
break;
}
default: // 其它时间,判断是否该重新开始显示了,用于控制亮度和避免闪烁
{
if (led_count > 50) // 此0.5ms时钟最小循环要大于15以上
led_count = 255;
}
}
led_count++; // 每次中断累加一次
} |
|