有些嵌入式问题挺磨人:设备上电后能跑,通信也正常,放一会儿突然没反应。按复位键,马上又活了。你给它加了看门狗,心里想着“这下总能兜底”,结果现场还是卡住。更尴尬的是,复位按钮有效,看门狗却像没看见。
这种现象我一般不急着把锅甩给某一行代码。按我的经验,它更像一个信号:系统没彻底掉电,也不一定进了普通死循环,而是卡在了看门狗看不准的位置。
先确认:复位到底是谁触发的
第一件事不是改程序,而是读复位标志。MCU 通常会留下 POR、BOR、外部复位、软件复位、WDT 复位等痕迹。上电后立刻把这些标志打印出来,或者存到一小段备份寄存器/Flash 日志里,再清除标志。
如果现场卡死后按下复位键,日志只显示外部复位,那看门狗可能根本没咬到。常见原因是喂狗位置放错、低功耗暂停了 WDT、时钟源异常,或者程序卡在总线等待里,但仍有某个地方在机械喂狗。
图:程序假死时,不要只盯着主循环,先把复位来源和死前现场留住。
看门狗没用,常见是“喂得太勤”
不少项目喜欢在主循环末尾喂狗。这个写法看起来规矩,其实有风险。某个任务已经卡住,主循环还在空转;通信线程锁死了,定时中断还在喂狗。系统对外已经不可用,看门狗却觉得“一切正常”。
更稳一点的做法,是让关键任务各自上报心跳。只有采样、通信、控制、存储这些关键链路都按时更新状态,才允许统一喂狗。这样看门狗盯的不是 CPU 是否还在跑,而是业务链路是否还活着。
复位能恢复,硬件边界也要查
复位按钮能恢复,常常说明外设状态被重新初始化了。I2C 从机拉低 SDA、SPI 忙标志不释放、传感器电源毛刺后进入异常状态,都可能让 MCU 在驱动层等不到返回。
供电也别跳过。电机启动、无线发射、继电器吸合时,3.3V 可能短暂下陷。电压没低到让 MCU 完整复位,却足够让外设状态乱掉。示波器抓一下 3.3V、复位脚、外设电源,比盯着代码猜更省时间。
我会按这几步落地
1. 保存复位来源。每次启动先记录复位标志,别让线索一上电就丢。
2. 加死前心跳。用 GPIO、环形日志或低成本串口,把主循环、关键任务、中断频率分开观察。
3. 改喂狗策略。别让单点喂狗代表系统健康,关键模块都报平安后再喂。
4. 给外设等待加超时。所有 while 等待寄存器标志的位置,都应该能退出、复位外设、上报错误。
5. 抓电源和复位脚。复位能恢复的问题,很多时候藏在电源、时钟、总线这些边界条件里。
看门狗不是万能保险,它更像最后一道门。门前面的健康检查做得粗,它就会被误导。下次遇到“程序假死、手动复位能好”的板子,先把复位来源、喂狗条件、外设超时、电源波形并起来看,问题范围通常会小很多。