蓝桥杯单片机 | 实战解析【进阶02】定时器中断下的长短按键识别与数码管动态显示

张开发
2026/4/19 1:20:02 15 分钟阅读

分享文章

蓝桥杯单片机 | 实战解析【进阶02】定时器中断下的长短按键识别与数码管动态显示
1. 定时器中断与长短按键识别原理在单片机开发中按键识别是最基础也最容易出问题的功能之一。我刚开始接触蓝桥杯单片机时最头疼的就是按键抖动和误触发问题。后来发现定时器中断是解决这些问题的银弹。定时器中断就像是你家厨房里的定时器。假设你在煮面条设置10分钟闹钟期间你可以去做其他事情比如看电视闹钟响了再回来处理面条。单片机中的定时器中断也是这个原理 - 每隔固定时间比如10ms产生一次中断在中断服务函数里处理关键任务。对于按键识别来说传统轮询方式有两个致命缺陷一是占用CPU资源二是难以精确计时。而定时器中断方案完美解决了这两个问题。具体到长短按键识别实现逻辑是这样的初始化定时器比如10ms中断一次按键按下时启动计时count_t变量累加按键释放时判断持续时间count_t 1001秒内→ 短按count_t ≥ 100 → 长按实测发现这种方案比delay延时靠谱多了。记得我第一次用delay实现长短按结果数码管显示会卡顿因为CPU被延时函数占用了。改用定时器中断后显示和按键处理各不影响效果丝般顺滑。2. 数码管动态显示避坑指南动态数码管显示是另一个容易翻车的点。很多同学反映按键处理时数码管会闪烁或熄灭根本原因是扫描周期没处理好。数码管动态显示原理就像快速切换的电灯开关。假设有6位数码管单片机需要以足够快的速度通常5-10ms轮流点亮每一位。如果这个过程中被长时间按键处理打断人眼就会看到闪烁。在CT107D平台上我的经验是#define TSMG 500 // 单个数码管点亮时长(微秒) void Display_Num() { // 位选控制 P2 (P2 0x1F) | 0xE0; // 消影处理 P0 0xFF; P2 0x1F; // 显示十位数 P2 (P2 0x1F) | 0xC0; P0 SMG_NoDot[num/10]; P2 0x1F; DelaySMG(TSMG); // 相同逻辑处理个位数... }这里有几个关键点消影处理必不可少先关闭所有段选每个数码管显示时间控制在500μs左右按键扫描必须放在主循环不能阻塞显示曾经有个坑我踩了三次忘记关闭位选锁存器P2 0x1F导致数码管显示乱码。后来养成习惯每次操作锁存器后立即恢复为IO模式。3. 完整代码实现与优化结合定时器中断和数码管显示完整的实现方案如下#include reg52.h sbit S4 P3^3; unsigned char num 28; // 初始值 bit F_key 0; // 按键状态标志 unsigned int count_t 0; // 计时变量 void Init_Timer0() { TH0 (65536 - 10000) / 256; // 10ms定时 TL0 (65536 - 10000) % 256; TMOD | 0x01; // 模式1 ET0 1; EA 1; TR0 1; } void Service_Timer0() interrupt 1 { TH0 (65536 - 10000) / 256; // 重装初值 TL0 (65536 - 10000) % 256; if(F_key) count_t; // 仅当按键按下时计时 } void Scan_Keys() { if(S4 0) { DelaySMG(1000); // 去抖动 if(S4 0) { count_t 0; // 计时清零 F_key 1; // 标记按下 while(S4 0) { Display_Num(); // 保持显示 } F_key 0; // 标记释放 // 长短按判断 if(count_t 100) num 0; // 长按清零 else if(num 100) num 0; // 短按累加 } } } void main() { Init_Timer0(); while(1) { Scan_Keys(); Display_Num(); } }这段代码有三个优化点值得注意定时器初值计算改用65536更规范按键状态用bit类型节省内存在按键保持期间持续调用Display_Num()4. 常见问题排查与解决在实际调试中我遇到过几个典型问题问题1按键反应迟钝原因去抖动延时过长比如用了20ms解决将去抖动延时降到5-10ms同时增加二次检测问题2长按误判为短按原因count_t变量溢出超过65535解决增加上限判断 if(count_t1000) count_t问题3数码管显示暗淡原因扫描周期过长解决调整TSMG值为300-800μs确保6位数码管整体刷新率50Hz问题4按键偶尔失灵原因中断优先级冲突解决在按键扫描关键代码段加入 EA0; ... EA1; 临时关闭中断有个调试技巧分享给大家可以用LED指示灯可视化调试。比如LED1亮表示进入按键中断LED2亮表示检测到长按 这样比单纯看数码管直观多了。最后提醒一点CT107D平台的J5跳线必须正确短接23脚否则按键信号无法输入。这个硬件问题曾经让我debug了一整天血泪教训啊

更多文章