看门狗定时器WDT从入门到实战 —— 单片机系统的守护者一、一句话理解看门狗定时器Watch Dog TimerWDT是单片机的一个硬件组成部分本质是一个递增或递减的定时器。程序正常运行时它会定期被喂重置一旦程序跑飞、死循环没人喂它它就会超时触发系统复位让程序重新从起点运行。通俗类比就像你设了一个每天早 8 点的闹钟平时你 7:50 就醒来关掉它闹钟永远不会响。但有一天你喝醉了睡过头闹钟就响了——强行把你叫醒。看门狗就是单片机的闹钟一切正常就不叫一出异常就叫。二、看门狗的前世今生2.1 为什么需要看门狗在嵌入式系统中软件 Bug 永远不可能 100% 测尽。即使代码本身正确外部干扰也可能让 CPU 执行出错。最常见的故障模式有故障类型现象软件能否自救死循环程序卡在while(1){}❌ 不能指针跑飞PC 指针跳到非法地址❌ 不能寄存器被改写外设状态异常⚠️ 部分能中断丢失关键事件未响应⚠️ 部分能时钟故障主时钟停振❌ 不能电压跌落CPU 处于亚稳态❌ 不能这些故障的共同点是软件已经无法依靠自身恢复。此时只有硬件强制复位这一招——这就是看门狗存在的意义。2.2 一个真实的工业现场案例某工厂产线上的 STM32 控制板运行 3 个月后偶发性死机现场人员必须断电重启。复现条件苛刻高湿度 变频器频繁启停。排查发现变频器启停瞬间产生强电磁干扰偶尔让 CPU 取到错误指令进入死循环。未启用看门狗是根因。启用 IWDG超时 1s后连续运行 2 年未再出现死机。结论看门狗是工业产品的兜底保险不是可选项是必选项。三、核心作用防止系统跑飞在工业现场单片机经常受到以下干扰⚡电气噪声— 电机、变频器产生的电磁干扰电源故障— 电压骤降、浪涌⛈️静电放电ESD— 冲击可能让寄存器翻转软件 Bug— 程序进入死循环或死锁️温度漂移— 时钟频率偏移导致时序异常射频干扰RFI— 无线设备、手机靠近时这些干扰会导致程序跑飞、卡死。看门狗的作用就是兜底——当软件层面无法自救时硬件层面强制复位让系统恢复运行。四、三个关键术语4.1 喂狗Feed / Kick the Dog含义在程序中主动触发看门狗计数器被刷新重新开始计算。实际操作就是调用一条指令如WDT_RESET()或写入特定寄存器告诉看门狗我还活着。喂狗频率分为两种模式快狗Fast-Mode频繁喂狗适合周期短的任务慢狗Slow-Mode较少喂狗适合初始化等耗时较长的阶段实际开发中通常在 WDT 初始化后先设为 Slow-Mode等周期任务正式运行后再切换为 Fast-Mode。4.2 杀狗Disable WDT含义禁用/关闭看门狗。调试阶段常用——你不想程序跑到一半被复位就先关掉看门狗。⚠️注意产品正式发布时务必开启看门狗杀狗只用于调试。一个常见的血案是调试时关了看门狗发版时忘了开量产后死机投诉雪片般飞来。4.3 咬狗Dog Biting / Timeout含义看门狗启动后计数器自动递减。如果在规定时间内没有收到喂狗指令计数器归零看门狗就会对 CPU 产生复位信号强制系统重启——俗称被狗咬了。小知识为什么叫狗——早期工程师把这种必须定期喂食否则就咬你复位的定时器形象地比作看门狗名字沿用至今。英文 “Kick the dog” 也是同样的隐喻。五、四类看门狗从软硬件控制类型划分看门狗可分为以下四类5.1 硬件看门狗Hardware WDT特征说明位置独立于 CPU 之外由专用硬件电路实现时钟由独立的时钟驱动外部无法更改复位方式输出信号引脚直接连接 CPU 的 RESET 引脚优势即使 CPU 完全死机硬件看门狗依然有效典型芯片MAX813、TPS3823、STWD100、SP706S适用场景高可靠性工业控制、汽车电子、航空航天等不允许死机的场景。5.2 软件看门狗Software WDT特征说明位置CPU 内置的一个计数器模块时钟由 CPU 本身的时钟决定配置计数器初值由软件设置超时时间可在一定范围内变化复位方式通过中断或异常信号触发系统重启适用场景对时间精度要求不高的通用嵌入式应用。5.3 独立看门狗Independent WDTIWDG特征说明时钟由专用低速时钟驱动如 LSI 32kHz关键优势即使主时钟发生故障独立看门狗依然有效独立性完全独立于主程序运行典型实现STM32 IWDG适用场景主时钟可能不稳定的场景如低功耗模式、时钟切换过程中。5.4 窗口看门狗Window WDTWWDG特征说明时钟由 APB1 时钟分频驱动独特机制设置了时间窗口——喂狗不能太早也不能太晚必须在窗口内检测范围既能检测程序卡死也能检测程序跑得太快异常加速适用场景对程序执行时间有严格要求的精密控制场景如电机控制、电力电子。5.5 四类看门狗横向对比维度硬件 WDT软件 WDTIWDGWWDG独立性★★★★★★★★★★★★★★主时钟故障有效✓✗✓✗时间精度中低中高可检测异常加速✗✗✗✓成本需外接芯片免费免费免费配置灵活度低高中中适用场景高可靠通用低功耗/抗主时钟故障精密时间控制六、工作流程┌─────────────────────────┐ │ 看门狗初始化 │ │ 设置计数器初始值 │ ────────────┬────────────┘ ▼ ┌─────────────────────────┐ │ 计数器开始计数 │ │ 初始值递减 │ └────────────┬────────────┘ ▼ ┌──────────────┐ │ 定时器0 │ ──┬────────┬── 是 │ │ 否 ▼ ▼ ┌──────────┐ ┌──────────────┐ │ 喂狗 │ │ 计数器继续 │ │ 重置计数 │ │ 递减 │ │ 回到起点 │ └─────────────┘ └────────── │ ▼ ┌──────────────┐ │ 定时器0 │ └──┬────────┬──┘ 否 │ │ 是 ▼ ▼ 继续计数 ┌──────────────┐ │ 看门狗产生 │ │ 复位信号 │ └──────┬───────┘ ▼ ┌──────────────┐ │ 系统复位 │ │ 程序重新运行 │ └──────────────┘关键步骤解读初始化阶段必须先设置计数器初值决定超时时间再启动看门狗。一旦启动无法关闭部分芯片支持。运行阶段计数器自动递减与主程序并行运行互不干扰。喂狗判断每次喂狗计数器被重装载回初值重新开始递减。超时触发一旦计数器归零立即产生复位信号。这个动作是硬件级别的不需要 CPU 参与——这也是看门狗可靠性的核心。七、STM32 看门狗实战详解STM32 系列单片机内置两类看门狗IWDG独立看门狗和WWDG窗口看门狗。下面分别讲解。7.1 IWDG 独立看门狗7.1.1 关键寄存器寄存器全称作用KRKey Register键寄存器。写0xCCCC启动 IWDG写0xAAAA喂狗写0x5555允许修改 PR/RLRPRPrescaler Register预分频寄存器。决定分频系数 /4、/8、/16…/256RLRReload Register重装载寄存器。12 位0~4095决定计数器初值SRStatus Register状态寄存器。PVUPR 是否可改、RVURLR 是否可改7.1.2 超时时间计算T_timeout 4 × 2^(PR2) × (RLR1) / f_LSI其中PR 0~6对应分频系数 /4、/8、/16、/32、/64、/128、/256RLR 0~4095f_LSI≈ 32kHzSTM32 内部低速 RC 振荡器误差 ±5%举例PR4分频 /64RLR624f_LSI32kHzT 4 × 2^6 × 625 / 32000 4 × 64 × 625 / 32000 5000ms 5s7.1.3 HAL 库代码示例#includestm32f1xx_hal.hIWDG_HandleTypeDef hiwdg;/* 初始化 IWDG超时 5s */voidMX_IWDG_Init(void){hiwdg.InstanceIWDG;hiwdg.Init.PrescalerIWDG_PRESCALER_64;// PR4分频 /64hiwdg.Init.Reload624;// RLR624hiwdg.Init.WindowIWDG_WINDOW_DISABLE;// 禁用窗口模式普通 IWDGif(HAL_IWDG_Init(hiwdg)!HAL_OK){Error_Handler();}}/* 喂狗 */voidWDT_Feed(void){HAL_IWDG_Refresh(hiwdg);// 等价于写 KR 0xAAAA}/* 主循环 */intmain(void){HAL_Init();SystemClock_Config();MX_IWDG_Init();while(1){task_sensor_read();WDT_Feed();// 喂狗task_can_send();WDT_Feed();// 喂狗task_uart_handle();WDT_Feed();// 喂狗}}7.1.4 寄存器级裸机操作/* 启动并配置 IWDG无 HAL 库 */voidIWDG_Init_BareMetal(void){/* 1. 启动 IWDG写 KR 0xCCCC */IWDG-KR0xCCCC;/* 2. 允许修改 PR、RLR写 KR 0x5555 */IWDG-KR0x5555;/* 3. 设置预分频PR4 → 分频 /64 */IWDG-PR0x04;/* 4. 设置重装载值RLR624 → 5s 超时 */IWDG-RLR624;/* 5. 重装载计数器写 KR 0xAAAA */IWDG-KR0xAAAA;}/* 喂狗重装载 */#defineIWDG_Feed()(IWDG-KR0xAAAA)7.2 WWDG 窗口看门狗7.2.1 与 IWDG 的核心区别维度IWDGWWDG时钟源LSI32kHz 独立APB1系统时钟分频计数器位数12 位7 位喂狗限制任意时刻必须在窗口内检测异常加速✗✓复位前中断✗✓可触发早期唤醒中断 EWI主时钟故障有效✓✗7.2.2 窗口机制详解WWDG 的计数器是 7 位0~0x7F递减计数。关键参数窗口上限值 W写入CFR寄存器的W[6:0]决定最早可喂狗时刻超时阈值 0x40计数器递减到0x3F时立即复位即T[6]由 1→0 触发喂狗规则0x7F 计数值 W禁止喂狗喂了就复位W ≥ 计数值 0x40允许喂狗喂狗重装载为 0x7F计数值 0x3F自动复位为什么禁止早喂——如果程序异常加速比如跳过了某些耗时的初始化会过早到达喂狗点。窗口机制可以捕捉到这种异常。7.2.3 HAL 库代码示例WWDG_HandleTypeDef hwwdg;voidMX_WWDG_Init(void){hwwdg.InstanceWWDG;hwwdg.Init.PrescalerWWDG_PRESCALER_8;// 分频hwwdg.Init.Window0x50;// 窗口值 Whwwdg.Init.Counter0x7F;// 计数器初值hwwdg.Init.EWIModeWWDG_EWI_ENABLE;// 使能早期唤醒中断if(HAL_WWDG_Init(hwwdg)!HAL_OK){Error_Handler();}}/* 早期唤醒中断回调复位前的最后机会 */voidHAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef*hwwdg){/* 这里可以做紧急保存写关键数据到 Flash/FRAM *//* 注意到这里已经离复位只有几十个时钟周期不能做长操作 */Save_Critical_Data();}/* 主循环喂狗必须在窗口内 */voidWWDG_Feed_InWindow(void){/* 读 SR 状态判断当前是否在窗口内 */if((hwwdg.Instance-CR0x7F)hwwdg.Init.Window){HAL_WWDG_Refresh(hwwdg);}}八、两种运行状态8.1 正常运行程序按预期执行在关键位置分散放置喂狗指令如WDT_RESET()。每隔一段时间CPU 主动喂狗计数器重置看门狗安静待命。// 示例正常喂狗流程voidmain_loop(void){WDT_Init(5000);// 初始化看门狗超时时间 5 秒while(1){task_1();// 执行任务 1WDT_Reset();// 喂狗 ✅task_2();// 执行任务 2WDT_Reset();// 喂狗 ✅task_3();// 执行任务 3WDT_Reset();// 喂狗 ✅}}8.2 异常运行被狗咬程序因干扰进入死循环喂狗指令所在的代码段永远执行不到。看门狗等不到喂狗信号计数器归零自动产生复位信号单片机从程序存储器的起始位置重新执行。// 示例死循环导致被咬voidmain_loop(void){WDT_Init(5000);// 初始化看门狗超时时间 5 秒while(1){task_1();// 执行任务 1WDT_Reset();// 喂狗 ✅// task_2() 中发生死循环task_2();// ← 卡在这里永远出不来WDT_Reset();// ❌ 永远执行不到task_3();WDT_Reset();}// 5 秒后 → 看门狗超时 → 系统自动复位 → 程序重新从 main() 开始}九、喂狗策略与常见陷阱9.1 喂狗位置黄金法则✅ 推荐位置❌ 禁止位置主循环每次任务结束后中断服务程序ISR内关键状态机切换时阻塞型延时函数内长任务分段完成点死循环while(1){}内while(1)顶部看门狗初始化前9.2 常见陷阱与避坑陷阱 1中断里喂狗错误代码voidTIM2_IRQHandler(void){// 1ms 定时中断WDT_Feed();// ❌ 错主程序死循环时中断仍会触发看门狗永远不会咬}问题即使主程序死循环定时中断仍会正常触发并喂狗。看门狗形同虚设。正确做法喂狗放在主循环。中断只置标志位主循环检查标志位再喂狗。陷阱 2超时时间设置过短错误超时设为 10ms但某个 Flash 写操作就要 30ms。结果每次写 Flash 都触发复位。正确超时时间应 ≥ 最长单任务时间 × 1.5 倍冗余。陷阱 3超时时间设置过长错误超时设为 10s。系统死机后要等 10s 才重启用户体验极差。正确通用场景 100ms~1s工控场景 1~5s初始化阶段用慢狗10s。陷阱 4单一喂狗点错误整个主循环只在末尾喂一次狗。如果某个任务卡住整段循环都跑不完。正确每个长任务后都喂一次分散喂狗点。陷阱 5调试时关狗发版忘了开典型血案开发阶段#define WDT_ENABLE 0量产代码忘了改回 1。对策用编译器宏强制检查——Release 构建配置中WDT_ENABLE必须为 1否则编译报错。9.3 多任务系统下的喂狗策略在 RTOS如 FreeRTOS环境下所有任务都活着才能喂狗避免某个任务死掉却被其他任务喂狗掩盖。/* FreeRTOS监控任务喂狗策略 */voidTask_Watchdog(void*pvParameters){for(;;){/* 检查所有任务是否都打卡过 */if(task_sensor_alivetask_comm_alivetask_log_alive){HAL_IWDG_Refresh(hiwdg);/* 清除打卡标志下一轮重新检查 */task_sensor_alive0;task_comm_alive0;task_log_alive0;}vTaskDelay(100);// 100ms 检查一次}}十、看门狗测试方法10.1 故意触发测试在产品验证阶段必须证明看门狗真的有效。常见做法/* 测试代码故意进入死循环验证看门狗 */voidTest_WDT(void){#ifdefWDT_TEST_MODEprintf(WDT test: entering infinite loop...\r\n);while(1){/* 故意什么都不做等看门狗咬 */}#endif}验证标准触发死循环后超时时间内系统自动复位复位后能正常启动看门狗不能咬死系统串口/日志能记录上次复位原因 IWDG_RESET10.2 复位原因识别STM32 通过RCC-CSR寄存器可识别复位来源voidCheck_Reset_Source(void){if(__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST)){printf(⚠️ Reset by IWDG! (Watchdog bite)\r\n);/* 可记录到 Flash 供后续分析 */}if(__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST)){printf(⚠️ Reset by WWDG! (Window watchdog)\r\n);}if(__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST)){printf(Reset by NRST pin (power-on/manual)\r\n);}/* 清除复位标志 */__HAL_RCC_CLEAR_RESET_FLAGS();}十一、多看门狗组合策略11.1 内部 IWDG 外部硬件 WDT最高可靠性的场景汽车电子、医疗、工业安全通常组合使用┌──────────────┐ │ STM32 CPU │──┬── 内部 IWDG一级保护超时 1s │ │ │ └──────────────┘ └── 外部 MAX813二级保护超时 2s │ ▼ 直接拉低 NRST 引脚为什么需要二级——如果 STM32 内部时钟树完全故障LSI 也挂了IWDG 不会工作。外部 WDT 用独立晶振能捕捉到这种极端情况。11.2 IWDG WWDG 互补IWDG主时钟故障兜底WWDG精密时间监控防止异常加速两者同时启用覆盖卡死和加速两种异常。十二、实际工程案例12.1 工业控制PLC 远程 IO 模块场景STM32F4 Modbus RTU 8 路模拟量输出部署在变电站。方案IWDG 超时 2s主循环 100ms × 20 倍冗余主循环每次完成 Modbus 处理后喂狗长操作如 EEPROM 写前临时切到慢狗复位原因写入 EEPROM维护人员可读取死机次数12.2 汽车电子TCU 程序烧录器场景DAM-C3241 通过 CANFD 给汽车 TCU 烧录程序烧录过程不能中断。方案WWDG 监控烧录时序每个 CAN 帧 100ms 间隔窗口 50~150msIWDG 兜底保护超时 5s覆盖 WWDG 漏检场景烧录关键步骤在 Flash 备份断点复位后能续烧12.3 光伏监测DAM-3053DC 数据采集场景野外光伏面板电压电流监测无人值守必须自恢复。方案IWDG 超时 5s采集周期 1s × 5 倍冗余DTU-1101 无线传输失败时不喂狗触发复位重连复位计数器记录通信故障次数超阈值进入低功耗维护模式十三、开发建议场景建议调试阶段先关闭看门狗杀狗方便排查问题产品发布必须开启看门狗这是最后一道防线初始化阶段使用慢狗模式给初始化留足时间主循环阶段切换为快狗模式频繁喂狗关键代码段在重要任务完成后立即喂狗中断服务程序避免在 ISR 中喂狗防止掩盖中断异常超时时间设置≥ 最长单任务 × 1.5 倍冗余复位原因识别启动时检查RCC-CSR记录复位来源量产测试必须验证 WDT 真的能触发复位多任务系统用任务打卡机制所有任务都活着才喂狗附录 A常用 MCU 看门狗对比MCU内置 WDT 类型独立时钟窗口模式备注STM32F1/F4IWDG WWDGLSI 32kHz✓WWDG主流工业级STM32G0/G4IWDG WWDGLSI 32kHz✓WWDG新一代高性能STM32L4IWDG WWDGLSI 32kHz✓WWDG低功耗ESP32TWDT IWDTRTC 时钟✗双核分任务看门狗Arduino AVR内置 WDTWDTON fuse✗8 位机2s 上限NXP LPC1768WWDT内部 RC✓类似 STM32 WWDGGD32F1/F3FWDGT WWDGTLSI 40kHz✓国产 STM32 兼容HC32F460WDTLSI 32kHz✗国产高性能附录 B术语速查表术语英文含义喂狗Feed / Kick重置计数器告诉 WDT “我还活着”杀狗Disable关闭看门狗仅调试用咬狗Bite / Timeout计数器归零触发复位快狗Fast-Mode短周期频繁喂狗慢狗Slow-Mode长周期少喂狗适合初始化IWDGIndependent Watchdog独立看门狗LSI 驱动WWDGWindow Watchdog窗口看门狗APB1 驱动EWIEarly Wakeup Interrupt早期唤醒中断复位前最后机会LSILow-Speed Internal内部低速 RC 振荡器约 32kHzKRKey Register键寄存器IWDG 控制RLRReload Register重装载寄存器IWDG 初值附录 C参考资源STM32F103 参考手册 RM0008IWDG/WWDG 章节STM32 HAL 库用户手册 UM1850ST 应用笔记 AN4065Watchdog usage on STM32原文知乎专栏 https://zhuanlan.zhihu.com/p/654005577