一、前言:为什么设备必须加看门狗?
很多小伙伴调试阶段设备完全正常,长时间上电运行就随机卡死、黑屏、不响应:
- 485/LoRa/WiFi总线干扰,程序指针跑飞卡死
- RTOS任务堆栈溢出、死锁导致系统停滞
- 电源纹波、静电干扰引发硬件异常
- 数组越界、野指针导致程序卡死循环
这类偶发问题无法靠代码逻辑完全规避,看门狗是嵌入式最后一道容错防线:程序正常运行定时喂狗,一旦卡死停止喂狗,自动硬件复位重启,保证设备永久在线。
二、两种看门狗核心区别(项目选型重中之重)
STM32提供两种看门狗,原理、时钟、使用场景完全不同,选错会导致频繁误复位或失效。
2.1 独立看门狗 IWDG(项目最常用)
时钟来源:内部独立RC时钟(40KHz),不依赖系统时钟。
核心特点:系统死机、时钟异常依旧正常工作,可靠性极高。
工作逻辑:倒计时递减,归零未喂狗 → 硬件强制复位。
适用场景:所有工业、物联网设备通用,解决卡死、跑飞问题。
2.2 窗口看门狗 WWDG(进阶容错)
时钟来源:系统总线时钟,依赖主时钟。
核心特点:有时间窗口限制,过早喂狗也会复位。
核心作用:防止程序卡死在正常循环、高速跑飞的异常场景。
适用场景:高可靠性产品、需杜绝程序异常跑循环的精密设备。
工程选型总结
- 普通物联网、监测设备:优先 独立看门狗IWDG,简单稳定、零误复位。
- 工业精密控制、高可靠设备:IWDG+WWDG双看门狗双重防护。
三、独立看门狗(IWDG)极简配置+实战代码
适配所有裸机、FreeRTOS项目,配置简单、稳定性拉满,推荐90%项目直接使用。
3.1 头文件 iwdg.h
#ifndef __IWDG_H
#define __IWDG_H
#include "stm32f10x.h"
void IWDG_Init(uint8_t prer,uint16_t rlr);
void IWDG_Feed(void);
#endif
3.2 驱动源码 iwdg.c
#include "iwdg.h"
/**
- @brief 独立看门狗初始化
- @param prer: 分频系数 0~6
- @param rlr: 重装载值 0~4095
- @retval 复位时间:约 1ms~26s 可调
*/
void IWDG_Init(uint8_t prer,uint16_t rlr)
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //解锁寄存器
IWDG_SetPrescaler(prer); //设置分频
IWDG_SetReload(rlr); //设置重装载值
IWDG_ReloadCounter(); //重载初值
IWDG_Enable(); //开启看门狗
}
//喂狗函数,定时调用
void IWDG_Feed(void)
{
IWDG_ReloadCounter();
}
3.3 工程初始化与喂狗逻辑(重点)
配置:分频64、重装载值625,复位时间约1s,适配绝大多数项目
int main(void)
{
SysInit();
OLED_Init();
ESP8266_Init();
IWDG_Init(IWDG_Prescaler_64,625); //1s复位阈值
while(1)
{
//正常业务逻辑
Env_Scan();
OLED_ShowData();
ESP8266_UploadData();
//正常运行定时喂狗,程序卡死则停止喂狗,自动复位
IWDG_Feed();
}
}
四、窗口看门狗(WWDG)进阶配置+容错原理
独立看门狗只能检测程序卡死不运行,无法检测程序跑飞、死循环高速运行,窗口看门狗可完美弥补该缺陷。
核心机制:必须在指定时间窗口内喂狗,喂太早、喂太晚,均直接复位,杜绝程序异常跑循环。
4.1 WWDG极简驱动代码
#include "wwdg.h"
//窗口看门狗初始化
void WWDG_Init(uint8_t tr,uint8_t wr,uint32_t fprer)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
WWDG_SetPrescaler(fprer);
WWDG_SetWindowValue(wr);
WWDG_Enable(tr);
}
//窗口看门狗喂狗
void WWDG_Feed(uint8_t tr)
{
WWDG_SetCounter(tr);
}
五、FreeRTOS项目专属喂狗方案(避坑重点)
RTOS多任务项目,绝对禁止在空闲任务、单一低优先级任务喂狗!
高危问题:高优先级任务死锁、卡死,低优先级任务依旧运行喂狗,看门狗彻底失效。
正确工程方案:多任务联动喂狗
核心思路:采集、无线、显示关键任务正常运行,才执行喂狗,任一核心任务卡死,停止喂狗触发复位。
//全局任务状态标记
uint8_t task_sensor_ok = 0;
uint8_t task_wifi_ok = 0;
//传感器任务正常运行标记
void Task_Sensor(void *pv)
{
while(1)
{
Env_Scan();
task_sensor_ok = 1;
vTaskDelay(pdMS_TO_TICKS(500));
}
}
//WiFi上传任务正常运行标记
void Task_Wifi(void *pv)
{
while(1)
{
Wifi_Upload();
task_wifi_ok = 1;
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
//单独看门狗巡检任务
void Task_WatchDog(void *pv)
{
while(1)
{
//所有核心任务正常运行,才喂狗
if(task_sensor_ok && task_wifi_ok)
{
IWDG_Feed();
//状态清零,下次循环重新判定
task_sensor_ok = 0;
task_wifi_ok = 0;
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
六、项目高频踩坑与解决方案
坑1:看门狗开启后,设备频繁无故复位
原因:喂狗间隔大于看门狗复位阈值、业务阻塞超时未喂狗。
解决:适当调大复位超时时间,所有阻塞操作加超时,避免长时间卡死不喂狗。
坑2:RTOS任务卡死,看门狗不复位
原因:喂狗放在空闲任务或低优先级任务,高优先级卡死不影响喂狗。
解决:采用多任务状态联动喂狗机制。
坑3:窗口看门狗极易误复位
原因:不了解窗口机制,喂狗时间过早。
解决:严格在窗口区间内喂狗,新手项目优先使用独立看门狗。
坑4:上电瞬间直接复位
原因:初始化完成前看门狗已倒计时结束。
解决:外设初始化、业务就绪后再开启看门狗。
七、工程级看门狗使用规范(量产必备)
- 初始化后置:所有外设、任务创建完成后,再开启看门狗。
- 喂狗周期匹配:业务最大阻塞时间 < 看门狗复位阈值。
- RTOS专属规范:禁止单任务喂狗,采用多任务状态校验喂狗。
- 故障可追溯:复位后读取看门狗标志位,判断是否为异常复位,便于调试。
- 高低搭配:普通设备用IWDG,高可靠设备双看门狗冗余防护。
八、全文总结
- 独立看门狗IWDG依托独立时钟,稳定性最强,是嵌入式设备防死机的基础必备配置;
- 窗口看门狗WWDG弥补程序跑飞死循环漏洞,用于高可靠工业设备进阶防护;
- 裸机项目简单定时喂狗即可,FreeRTOS项目必须采用多任务联动喂狗,杜绝防护失效;
- 看门狗是设备长期稳跑的最后防线,配合前文低功耗优化、通信容错、故障排查,可实现设备7×24小时无人值守稳定运行。