AVR驱动7段数码管60秒倒计时定时器不准及显示异常问题咨询
计时不准确故障修复
故障原因
- 延时函数的溢出判断运算符优先级错误:
while (TIFR & (1<<TOV0)==0);中==优先级高于按位与&,实际执行逻辑等效于TIFR & 0,while循环直接退出,延时完全失效。 - 计数变量未重置:counter达到123触发减计数后没有清零,只能等待counter溢出后才能再次触发,计时逻辑完全错误。
- 计时参数小误差:8MHz时钟预分频256时,8位定时器0单次溢出时间为8.192ms,1秒需要约122次溢出,原参数123误差不大,非核心问题。
修复代码
void T0delay() { TCNT0 = 0; TCCR0 = 0x04; // 加括号调整优先级,正确判断溢出标志 while ((TIFR & (1<<TOV0)) == 0); TIFR = (1<<TOV0); // 写1清除溢出标志,写法更规范 }
主循环触发减计数后添加counter清零:
if(counter == 122) { counter = 0; // 新增重置计数 // 原有减计数逻辑 }
倒计时到0后显示异常故障修复
故障原因
- 无7段数码管段码映射:直接将数字0~9输出到IO口,IO输出的数值和数码管点亮需要的段码不匹配,比如共阴数码管显示1需要段码0x06,而非数字1对应的0x01。
- 寄存器下溢:倒计时到0后没有停止计数逻辑,PORTD为0时执行
PORTD--会发生无符号数下溢,变成0xFF输出乱码。 - 停止条件逻辑错误:原判断
if(PORTD == 0 & PORTC == 0 )错用按位与&而非逻辑与&&,且没有真正停止计数逻辑。 - 数值与输出端口混用:直接用PORTD/PORTC存储计数数值,导致端口输出始终是数值而非段码,显示天然异常。
修复方案
新增段码表,分离计数变量和输出端口,添加停止逻辑,完整修复后代码如下:
#define F_CPU 8000000UL #include <avr/io.h> // 共阴7段数码管段码表,对应数字0~9,共阳则所有值取反即可 unsigned char seg_code[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; void T0delay() { TCNT0 = 0; TCCR0 = 0x04; while ((TIFR & (1<<TOV0)) == 0); TIFR = (1<<TOV0); } int main(void) { int counter = 0; int sec_unit = 0; // 个位计数变量 int sec_ten = 6; // 十位计数变量 DDRC = 0xff; DDRD = 0xff; // 初始输出查表后的段码 PORTC = seg_code[sec_unit]; PORTD = seg_code[sec_ten]; while (1) { // 倒计时到0后停止所有计数逻辑 if(sec_ten == 0 && sec_unit == 0) continue; T0delay(); counter++; if(counter == 122) { counter = 0; sec_unit--; if(sec_unit < 0) { sec_unit = 9; sec_ten--; } // 查表得到段码后输出 PORTC = seg_code[sec_unit]; PORTD = seg_code[sec_ten]; } } }
内容的提问来源于stack exchange,提问作者Khaled Haggag
相关产品推荐
相关产品推荐

