【STM32】[特殊字符] WWDG(窗口看门狗)学习笔记
🧾 STM32 WWDG(窗口看门狗)学习笔记
🔧 一、基本概念
WWDG(Window Watchdog) 是 STM32 内置的一种硬件看门狗定时器,主要用于系统故障检测与自动复位。
-
🧠 工作方式:
从设定值递减计数器,必须在指定时间窗口内重装(喂狗),否则复位系统。 -
✅ 目的:
监控主程序是否卡死、失控或未按时执行关键任务。
🧩 二、关键参数说明
参数 | 含义 | 取值范围 | 备注 |
---|---|---|---|
Prescaler | 预分频器 | 1, 2, 4, 8 | 控制计数递减速度,计数时钟 = PCLK1/(4096×Prescaler) |
Counter Value | 自由递减计数器初始值 | 64(0x40)~~127(0x7F) | 每次喂狗时写入该值 |
Window Value | 喂狗窗口上限 | 64(0x40)~~127(0x7F) | 计数器值必须 ≤ Window 且 ≥ 64 时喂狗 |
EWI (Early Wakeup Interrupt) | 计数器到达 64 触发中断 | 启用/禁用 | 可提前执行紧急处理,保存数据等 |
📐 三、计数时钟计算
计数器递减频率(单位 Hz):
f WWDG = P C L K 1 4096 × Prescaler f_{\text{WWDG}} = \frac{PCLK1}{4096 \times \text{Prescaler}} fWWDG=4096×PrescalerPCLK1
- 例如:
PCLK1 = 180 MHz, Prescaler = 8
则:
f ≈ 180 , 000 , 000 4096 × 8 = 5493 Hz f \approx \frac{180,000,000}{4096 \times 8} = 5493 \text{ Hz} f≈4096×8180,000,000=5493 Hz
每次递减周期约 182 μ s 182 \mu s 182μs
🧮 四、超时时间估算
最大超时时间:
T timeout = ( C o u n t e r − 64 ) × 1 f WWDG T_{\text{timeout}} = (Counter - 64) \times \frac{1}{f_{\text{WWDG}}} Ttimeout=(Counter−64)×fWWDG1
- 例如,Counter = 127,Prescaler = 8,PCLK1 = 180 MHz
- 递减步数 = 127 - 64 = 63
- 超时时间 = 63 × 182 μ s ≈ 11.5 m s 63 \times 182 \mu s \approx 11.5 ms 63×182μs≈11.5ms
⏳ 五、窗口机制说明
-
只有当计数器值满足:
64 ≤ Counter ≤ Window 64 \leq \text{Counter} \leq \text{Window} 64≤Counter≤Window
才允许喂狗。
-
过早喂狗(Counter > Window)会触发复位。
-
过晚喂狗(Counter < 64)会触发复位。
🚨 六、Early Wakeup Interrupt(EWI)
-
计数器递减到 64(0x40)时触发中断。
-
该中断只会被硬件清除复位后才有效。
-
提供“最后抢救”机会,可用来:
- 记录故障信息
- 保存重要数据(Flash、RAM)
- 触发报警指示等
-
注意: EWI 只有在系统未完全死机且中断响应正常时才会触发。
⚠️ 七、常见问题与误区
问题 | 原因 | 建议 |
---|---|---|
看门狗一上电就复位 | Counter = Window = 64,窗口过窄 | 设置更大的 Counter 和 Window,扩展喂狗时间窗口 |
喂狗失败,程序经常复位 | 喂狗时机不对(早或晚) | 使用定时器或任务同步确保喂狗时间精准,避免“早喂”“晚喂” |
程序死机未复位 | 未启用看门狗 | 确保正确配置并使能看门狗 |
没有保存数据 | 程序完全卡死或未启用 EWI | 启用 EWI 中断,在中断内保存关键数据 |
中断不触发 | NVIC 未使能,或 EWI 未设置 | 确保 NVIC 使能 WWDG_IRQn,且打开 EWI 模式 |
✅ 八、示例配置代码(PCLK1 = 45 MHz 实际示例)
WWDG_HandleTypeDef hwwdg;void MX_WWDG_Init(void)
{hwwdg.Instance = WWDG;hwwdg.Init.Prescaler = WWDG_PRESCALER_8; // 预分频8hwwdg.Init.Window = 100; // 窗口值100hwwdg.Init.Counter = 127; // 初始计数127hwwdg.Init.EWIMode = WWDG_EWI_ENABLE; // 使能 EWI 中断if (HAL_WWDG_Init(&hwwdg) != HAL_OK){Error_Handler();}// 使能中断优先级及中断HAL_NVIC_SetPriority(WWDG_IRQn, 5, 0);HAL_NVIC_EnableIRQ(WWDG_IRQn);
}
🛠️ 九、中断服务及喂狗示例
void WWDG_IRQHandler(void)
{HAL_WWDG_IRQHandler(&hwwdg);
}void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{// 翻转 GPIO,比如 PE9(LED)HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_9);// 喂狗,重装计数器,防止复位HAL_WWDG_Refresh(hwwdg);
}
🔄 十、主循环示例
int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_WWDG_Init();while (1){// 主循环无需主动喂狗,交给 EWI 中断处理}
}
📌 十一、CubeMX 查看 PCLK1 时钟频率
- 打开 CubeMX 工程,点击顶部的 Clock Configuration 标签。
- 找到 APB1 clock (PCLK1) 数值(单位 MHz),确认实际频率。
- 以此频率计算 WWDG 计数时钟,确认超时时间是否合理。
🎯 十二、RTOS 环境下建议
- 创建专门监控任务,周期检查系统健康。
- 健康时调用喂狗,异常时停止喂狗以触发复位。
- 利用 EWI 做故障日志记录。
- 合理设置 Prescaler、Window、Counter,保证窗口足够宽,避免频繁复位。
⚙️ 十三、计算示例(PCLK1 = 45 MHz)
参数 | 计算过程 | 结果 |
---|---|---|
Prescaler | 8 | |
计数频率 | 45,000,000 / (4096 × 8) | 1373 Hz |
计数周期 | 1 / 1373 | 728 μs |
递减次数 | 127 - 64 = 63 | |
最大超时时间 | 63 × 728 μs | 45.86 ms |
喂狗安全窗口宽度 | (Window - 64) × 728 μs (Window=100) | 36 × 728 μs ≈ 26.2 ms |
📝 备注
- Window 值越大,喂狗窗口越宽,越容易稳定
- Counter 值越大,超时时间越长
- Prescaler 越大,计数递减越慢,超时时间越长
- 请务必结合实际时钟频率调整参数!