想象一下你正在开发一个工业温控设备,系统需要24小时不间断运行。突然某天凌晨3点,程序因为电磁干扰跑飞了,温度控制失效导致生产线报废——这种场景对嵌入式开发者来说简直是噩梦。看门狗(Watchdog)就是为解决这类问题而生的硬件安全机制,它像电路中的保险丝一样,在系统异常时强制复位恢复运行。
STM32F103提供了两种看门狗:独立看门狗(IWDG)和窗口看门狗(WWDG)。它们的核心原理都是计数器递减,区别在于对"喂狗"时机的宽容度。IWDG像一位随和的管家,只要定期投喂(重置计数器)就不会触发复位;WWDG则像严格的时间管理者,喂得太早或太晚都会引发系统重启。
打开STM32参考手册的IWDG章节,可以看到其硬件结构包含三个关键部件:
计算最大看门时间的公式为:
code复制最大看门时间 = (1/40000) × 分频系数 × (重载值+1)
例如使用256分频和4095重载值时:
c复制(1/40000) × 256 × 4096 ≈ 26.2秒
配置IWDG需要掌握四个关键寄存器:
典型配置流程如下:
c复制IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); // 解锁PR/RLR
IWDG_SetPrescaler(IWDG_Prescaler_256); // 设置256分频
IWDG_SetReload(1249); // 设置1秒超时(40000/256*1250)
IWDG_Enable(); // 启动看门狗
while(1) {
Delay_ms(800);
IWDG_ReloadCounter(); // 喂狗
}
在我的一个光伏逆变器项目中,曾遇到IWDG莫名复位的问题。后来发现是中断服务程序执行时间过长,导致主循环喂狗不及时。解决方案有两种:
实测发现IWDG的精度约为±5%,不适合对时间精度要求高的场景。但其优点在于:
WWDG最显著的特点是引入了"喂狗窗口"概念:
其硬件设计更为复杂:
控制寄存器(WWDG_CR):
配置寄存器(WWDG_CFR):
时序计算示例:
c复制PCLK1=36MHz, 预分频=8 → 计数周期=1/(36M/4096/8)≈0.91ms
设置计数器初值=54(0x36),窗口值=43:
- 最早喂狗时间:0.91ms × (54-43) ≈ 10ms
- 最晚喂狗时间:0.91ms × (54+1) ≈ 50ms
下面是一个LED闪烁保护示例:
c复制RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
WWDG_SetPrescaler(WWDG_Prescaler_8);
WWDG_SetWindowValue(43|0x40); // 必须保持bit6=1
WWDG_Enable(54|0x40); // 初始计数器值
while(1) {
Delay_ms(30); // 在10-50ms窗口内喂狗
WWDG_SetCounter(54|0x40); // 重置计数器
}
经实测,WWDG的时间误差<±1%,非常适合:
| 特性 | IWDG | WWDG |
|---|---|---|
| 时钟源 | 独立LSI(40kHz) | PCLK1(通常36MHz) |
| 最大看门时间 | 26.2秒 | 约58.25ms |
| 时间精度 | ±5% | ±1% |
| 喂狗窗口 | 无限制 | 严格时间窗口 |
| 适用场景 | 环境监测、数据记录 | 实时控制、通信协议 |
| 抗干扰能力 | 强(独立时钟) | 依赖系统时钟稳定性 |
在智能家居网关项目中,我采用了两级看门狗方案:
配置要点:
当看门狗频繁复位时,可按以下步骤排查:
c复制if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST)) {
BKP_WriteBackupRegister(BKP_DR1, 0xAAAA);
}
通过合理配置和组合使用两种看门狗,我的工业控制器项目实现了连续运行300天无故障的可靠表现。记住,好的看门狗策略不是为了防止复位,而是确保复位后系统能安全恢复。