2、硬件看门狗(WDT)原理:独立看门狗与窗口看门狗的区别,喂狗机制与溢出时间计算,硬件电路设计要点。
各位工程师朋友,咱们接着聊。上一章讲了系统级故障的宏观分类,这一章咱们扎进一个具体但极其关键的模块——硬件看门狗。
说实话,我见过太多产品因为看门狗设计不当,在现场频繁复位,客户投诉不断。你想想看,一个本该在无人值守环境下稳定运行几年的设备,结果三天两头死机重启,这谁受得了?所以,把看门狗吃透,是工业MCU设计的必修课。
2.1 独立看门狗(IWDG)与窗口看门狗(WWDG)的区别
很多初学者会问:都是看门狗,干嘛还分两种?其实它们的定位完全不同。
独立看门狗(IWDG),说白了就是一个独立的、由内部低速RC振荡器驱动的计数器。它不依赖主时钟,即使主时钟挂了,它照样跑。我习惯叫它“最后的防线”。
- 时钟源:独立的LSI(低速内部振荡器),约40kHz(具体看芯片手册)。
- 特点:一旦启动,无法关闭(除非复位)。
- 应用场景:防止程序跑飞、死循环等严重故障。
窗口看门狗(WWDG),则更“智能”一些。它要求你在一个特定的时间窗口内喂狗——不能太早,也不能太晚。太早喂狗,说明程序执行节奏太快,可能跳过了某些关键步骤;太晚喂狗,说明程序卡住了。
- 时钟源:来自主时钟(APB1),与系统时钟同步。
- 特点:有上下限窗口,喂狗时机必须精确。
- 应用场景:对程序执行时序有严格要求的场合,比如电机控制、通信协议栈。
核心区别一句话总结:IWDG是“你必须在超时前喂我”,WWDG是“你必须在超时前且不能太早喂我”。
2.2 喂狗机制与溢出时间计算
喂狗,就是定期给看门狗计数器“清零”,防止它溢出复位。但怎么喂、什么时候喂,这里头有讲究。
独立看门狗的喂狗与时间计算
IWDG的溢出时间由预分频器和重装载寄存器决定。公式很简单:
溢出时间 = (重装载值 + 1) × (4 × 2^预分频系数) / LSI频率
举个例子,STM32F103的LSI典型值是40kHz。我设预分频系数为4(即64分频),重装载值为625:
溢出时间 = (625 + 1) × (4 × 2^4) / 40000
= 626 × 64 / 40000
≈ 1.0016 秒
嗯,差不多1秒。我在项目中一般习惯留20%~30%的余量,比如程序主循环周期是500ms,我会把看门狗溢出时间设在600ms~700ms左右。为什么?因为极端情况下,中断响应、任务切换可能会引入额外延迟。
我的个人习惯:喂狗点不要放在中断服务函数里。我曾经见过一个项目,把喂狗放在定时器中断中,结果主程序死循环了,中断还在跑,看门狗永远不复位——这等于把看门狗废了。喂狗一定要放在主循环的关键路径上。
窗口看门狗的喂狗与时间计算
WWDG的计算稍微复杂一点。它有一个7位的递减计数器(T[6:0]),还有一个窗口寄存器(W[6:0])。喂狗必须在计数器值大于窗口值且小于等于0x40时进行。
喂狗允许范围:窗口值 < 计数器值 ≤ 0x40
溢出时间计算公式:
溢出时间 = (计数器值 + 1) × (4096 × 2^预分频系数) / PCLK1频率
假设PCLK1=36MHz,预分频系数为8,计数器初始值设为0x7F(127),窗口值设为0x5F(95):
最大溢出时间 = (127 + 1) × (4096 × 8) / 36000000
= 128 × 32768 / 36000000
≈ 0.1165 秒
喂狗必须在计数器值从127递减到95之间的这段时间内完成。说白了,窗口只有32个计数值的时间,大约29ms。这个窗口很窄,对程序实时性要求很高。
注意:WWDG的计数器一旦启动,不能像IWDG那样通过软件停止。而且,如果喂狗时计数器值已经小于窗口值,会立即产生复位。所以,用WWDG时,一定要确保喂狗代码的执行时间抖动在可控范围内。
2.3 硬件电路设计要点
看门狗虽然是MCU内部模块,但硬件电路设计同样不能马虎。我踩过不少坑,这里分享几个关键点。
2.3.1 外部复位电路与看门狗的关系
很多MCU的看门狗复位输出会连接到外部复位芯片或RC复位电路。这里有个容易忽略的问题:如果外部复位电路的时间常数太大,看门狗复位脉冲可能被“吃掉”,导致MCU无法正常复位。
我建议:
- 看门狗复位输出直接连接到MCU的复位引脚,中间不要加太大的电容。
- 如果必须使用外部复位芯片,选择带有看门狗输入功能的型号(如MAX706、TPS3823等)。
2.3.2 电源去耦与看门狗稳定性
看门狗对电源噪声很敏感。尤其是独立看门狗,它的LSI振荡器对电源纹波容忍度较低。我在一个项目中遇到过:设备在电机启动瞬间,电源跌落导致看门狗误复位。
解决办法:
- 在MCU电源引脚附近放置0.1μF+10μF的去耦电容。
- 如果条件允许,给看门狗模块单独加一个LC滤波器。
- PCB布局时,看门狗相关的走线远离大电流回路。
2.3.3 外部看门狗芯片的选型与设计
有些高可靠性场合,MCU内部看门狗还不够,需要外加独立看门狗芯片。比如:
| 芯片型号 | 超时时间 | 特点 |
|---|---|---|
| MAX706 | 1.6s | 带手动复位输入,低功耗 |
| TPS3823 | 1.6s | 带看门狗使能引脚 |
| ADM706 | 1.6s | 工业级温度范围 |
外部看门狗的设计要点:
- 喂狗信号(WDI)必须用开漏输出,加上拉电阻。
- 看门狗超时时间要大于MCU内部看门狗,形成“双重保护”。
- 复位输出通常为低有效,直接连到MCU复位引脚。
避坑指南:我曾经在一个项目中,外部看门狗的喂狗引脚和MCU的GPIO之间没有加限流电阻。结果GPIO配置为推挽输出时,与看门狗芯片的内部上拉电阻形成冲突,导致电平异常。后来我在中间串了一个1kΩ电阻,问题解决。
2.4 实际项目中的喂狗策略
理论讲完了,咱们聊聊实战。喂狗策略直接决定了看门狗的有效性。
策略一:主循环喂狗
最简单的方式,在主循环末尾喂狗。但问题在于:如果某个子函数陷入死循环,主循环根本跑不到喂狗点。
策略二:多任务喂狗
在RTOS中,每个关键任务都设置一个标志位,只有所有标志位都置位了,才允许喂狗。这样,任何一个任务卡死,看门狗都会复位。
void Watchdog_Feed(void)
{
if (Task1_Flag && Task2_Flag && Task3_Flag)
{
HAL_IWDG_Refresh(&hiwdg);
Task1_Flag = 0;
Task2_Flag = 0;
Task3_Flag = 0;
}
}
策略三:分层喂狗
对于复杂系统,我习惯用两级看门狗:内部IWDG作为第一级,外部看门狗作为第二级。内部看门狗超时时间短(几百毫秒),用于快速响应;外部看门狗超时时间长(几秒),用于兜底。
我的经验:喂狗代码不要写得太复杂。我见过有人把喂狗函数里塞了各种状态判断、日志打印,结果喂狗本身就成了故障点。喂狗就是喂狗,越简单越好。
好了,这一章的内容就到这里。看门狗设计看似简单,但真正做好并不容易。下一章咱们聊聊电压监测与掉电保护,这也是工业现场常见的故障场景。到时候见。