根据下面图中的电路原理图和代码解决十位数码管显示时闪烁的问题显示




我曾经遇到过类似的问题,十位数码管显示闪烁通常是因为动态扫描频率过低或消隐逻辑不完善导致的。结合提供的代码和电路,分析如下:
display函数每次只显示十位和个位各1ms,若主循环中存在较长延时或任务阻塞,会导致扫描间隔超过人眼识别的临界值(约50Hz),出现闪烁。timer_count递增和按键检测可能占用过多时间,导致显示刷新不及时。核心思路:提高扫描频率,确保每位显示时间均匀,并完善消隐流程。
代码优化:
void display(unsigned int digit) {
unsigned char ten_bit = digit / 10; // 十位
unsigned char unit_bit = digit % 10; // 个位
// 显示十位
A1 = 1; B1 = 1; C1 = 1; // 选通十位数码管(假设A1/B1/C1为位选信号)
P0 = 0x00; // 先消隐前一位
delay_ms(1); // 消隐延时
P0 = tab[ten_bit]; // 发送十位段码
delay_ms(2); // 显示时间(建议2-5ms,提高扫描频率)
// 显示个位
A1 = 0; B1 = 1; C1 = 1; // 选通个位数码管
P0 = 0x00; // 先消隐前一位
delay_ms(1);
P0 = tab[unit_bit];
delay_ms(2);
P0 = 0x00; // 整体消隐(可选,避免余晖)
}
优化点:
P0,避免残影。 核心思路:用定时器中断独立处理显示刷新,避免主循环任务干扰扫描频率。
步骤:
代码框架:
unsigned char current_bit = 0; // 当前扫描位(0:十位,1:个位)
void Timer0_Init() {
TMOD |= 0x01; // T0模式1(16位定时器)
TH0 = 0xFC; // 1ms定时初值(12MHz晶振)
TL0 = 0x66;
ET0 = 1; // 使能T0中断
EA = 1; // 总中断使能
TR0 = 1; // 启动定时器
}
void Timer0_ISR() interrupt 1 {
TH0 = 0xFC; // 重新装载初值
TL0 = 0x66;
if (current_bit == 0) { // 显示十位
A1 = 1; B1 = 1; C1 = 1; // 选通十位
P0 = tab[count_seconds / 10];
current_bit = 1;
} else { // 显示个位
A1 = 0; B1 = 1; C1 = 1; // 选通个位
P0 = tab[count_seconds % 10];
current_bit = 0;
}
}
void main() {
Timer0_Init(); // 初始化定时器
while(1) {
// 主循环仅处理计数和按键,显示由中断自动刷新
// ...原有按键检测和计数逻辑...
}
}
优势:
delay_ms阻塞导致的显示延迟,适合复杂任务场景。| 方案 | 实现难度 | 稳定性 | 适用场景 |
|---|---|---|---|
| 方案1 | 低 | 较高 | 简单任务,无中断场景 |
| 方案2 | 中 | 最高 | 多任务并行,高实时性 |
推荐方案1:无需修改硬件和中断系统,直接优化现有扫描逻辑,见效快。若后续需扩展功能,可再升级为方案2。
希望以上方案能解决你的问题!如果对代码实现或Proteus仿真有疑问,请继续留言。期待你的反馈,也请楼主采纳~