看门狗定时器(Watchdog Timer,WDT)是嵌入式系统中保障程序可靠运行的最后一道防线。当程序因异常进入死循环或“跑飞”时,WDT 会在超时后强制复位 MCU,使系统恢复正常。然而,WDT 用得不规范,反而可能让这道防线形同虚设。本文结合工程实践,总结四条关键技巧。
一、实测 WDT 实际运行周期:示波器观测法
WDT 超时周期受时钟源、预分频/后分频系数、温度及器件离散性影响,数据手册给出的标称值未必等于实际值。推荐用以下方法实测:
方法:在 CLRWDT 指令前后翻转一个 I/O 引脚(或驱动 LED),用示波器观察该引脚波形。
LED_PIN = 1; // 置高 CLRWDT(); // 清狗 LED_PIN = 0; // 置低 |
判读要点:
•若系统正常运行,示波器上可测得清狗动作的实际间隔周期,即程序主循环的执行周期;
•若故意注释掉 CLRWDT,可观察到 WDT 超时后复位造成的周期性重启波形,从而测得真实的 WDT 超时时间。
这一实测值是后续设计清狗策略的基准。
二、全程序只保留一处CLRWDT
原则:整个工程中,CLRWDT应当且只应当出现在一个位置(通常是主循环的固定点)。原因如下:
•WDT的本质要求是:程序必须在超时周期之内完成一次清狗,否则触发复位;
•若代码中散落多个CLRWDT,超时窗口的起算点将变得难以追踪——任何一处清狗都会重置计数,导致你无法准确判断“从最后一次清狗到下一次清狗”的最长路径是否满足时序要求;
•单点清狗还能保证:只有主循环完整地、按预期路径执行到该点,看门狗才会被清除。一旦程序卡死在中途任意环节,WDT 必然超时并复位——这正是看门狗存在的意义。
注意:清狗点应放在主循环中“必须经过”且能代表程序健康运行的位置,而不是随意放置。 |
三、切勿在定时器中断中清狗
这是一个常见但危险的反模式。先看一个典型错误做法:
void __interrupt() ISR(void) { if (TMR0IF) { CLRWDT(); // 错误:不要在中断服务程序中清狗 TMR0IF = 0; } } |
为什么不行:WDT 的设计初衷是处理“不可逃脱的死循环”这类致命异常。关键在于——即使主程序卡死在死循环中,定时器中断通常仍可正常触发(只要全局中断未被关闭)。这会造成:
1. 主程序陷入死循环,系统功能已失效;
2. 定时器中断照常触发,CLRWDT 在中断里被执行,看门狗不断被清除;
3. 中断返回后,程序重新回到死循环继续卡死;
4. 结果:系统永久瘫痪,但 WDT 永远不会复位——看门狗彻底失效。
正确做法是把CLRWDT放在主循环中,让“主程序是否健在”成为能否清狗的唯一判据。
四、WDT 的使能方式:配置位与软件控制
WDT有两种激活途径,可根据产品需求选择。
方式一:配置位使能(推荐用于量产)
#pragma config WDTEN = ON |
在配置字(Configuration Bits)中使能后,WDT从芯片上电起始终运行,无法被软件关闭,可靠性最高,适合对安全性要求高的量产产品。
方式二:软件使能(SWDTEN 位)
在配置位中将WDT设为软件可控模式(如WDTEN = SW或OFF,视具体器件而定),然后在代码中置位SWDTEN使能:
#pragma config WDTEN = SW // 允许软件控制 // 在初始化代码中: WDTCONbits.SWDTEN = 1; // 软件开启 WDT |
此方式便于调试阶段灵活开关WDT(调试器单步/断点时若WDT一直运行会频繁复位,影响调试体验),量产前再切换为配置位强制使能。
提示:不同系列器件的寄存器命名和控制细节有差异,使用前请查阅对应器件数据手册的Watchdog Timer章节,确认SWDTEN位所在寄存器及配置字选项。 |
五、小结
技巧 | 核心要点 |
示波器实测 | 翻转I/O + CLRWDT,实测清狗周期与超时时间 |
单点清狗 | 全程序仅一处CLRWDT,保证超时窗口可预测 |
禁止中断清狗 | 中断在死循环中仍触发,会使WDT永久失效 |
双途径使能 | 量产用配置位WDTEN = ON;调试用SWDTEN软件控制 |
一句话总结:看门狗的价值在于“程序失控时一定能复位”,所有使用技巧都围绕一个目标——确保清狗动作只能由健康运行的主程序发出。