做消费类产品的朋友应该都有体会:实验室里跑得好好的,一到客户手上就出问题。电磁干扰、电源毛刺、静电ESD……这些现场环境的东西你实验室里根本模拟不出来。所以产品的可靠性设计特别重要,而看门狗就是可靠性设计的底线。
今天聊聊STM32的看门狗怎么用,以及一些故障保护的思路。
一、STM32的三种”看门狗”
STM32F1其实有三种watchdog机制:
1. 独立看门狗(IWDG)
• 用LSI(约40kHz)驱动,精度不高但独立于主时钟
• 就算主时钟挂了它还在跑
• 12位递减计数器,预分频和重载值可编程
• 超时后产生复位
2. 窗口看门狗(WWDG)
• 用PCLK2驱动,精度取决于系统时钟
• 不仅可以检测”太慢”(超时),还能检测”太快”(提前喂狗)
• 所以叫”窗口”看门狗——你只能在规定的窗口时间内喂狗
3. SysTick看门狗(软件看门狗)
• STM32没有硬件实现,用软件模拟
• 在SysTick中断里计数,主循环定期清零
• 最灵活,可以做成多级看门狗
二、独立看门狗配置实战
#include "stm32f10x_iwdg.h"
void IWDG_Init(uint32_t prescaler, uint32_t reload_value)
{
// 1. 使能LSI(独立看门狗的时钟源)
RCC_LSICmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);
// 2. 使能寄存器访问(写IWDG_PR和IWDG_RLR前要先开访问权限)
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
// 3. 配置预分频器和重载值
// LSI约40kHz,预分频64后 = 40000/64 = 625Hz,每个计数周期 = 1.6ms
// 重载值499 -> 超时时间 = (499+1) * 1.6ms = 800ms
IWDG_SetPrescaler(prescaler);
IWDG_SetReload(reload_value);
// 4. 重载计数器(写入重载值后计数器立即重置)
IWDG_ReloadCounter();
// 5. 使能看门狗
IWDG_Enable();
}
void IWDG_Feed(void)
{
IWDG_ReloadCounter();
}
三、窗口看门狗的妙用
窗口看门狗比独立看门狗高级在它可以检测”喂狗太快”的情况。正常逻辑是:
时间轴:|—窗口开启—|—喂狗窗口—|—窗口关闭—|
• 窗口开启后到窗口关闭前:可以喂狗
• 窗口关闭后到下次窗口开启:如果这时候喂狗会立即复位
适用场景:某个关键任务有严格的执行时间要求,你希望它必须在规定的时间内执行,不能太快也不能太慢。
void WWDG_Init(uint8_t window_value)
{
// 1. 使能WWDG时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
// 2. 配置窗口值和分频器
// PCLK2 = 72MHz, 分频器8 -> 9MHz计数时钟
// 窗口值 = 0x60 (二进制01100000),计数器初始值也要>窗口值
WWDG_SetWindowValue(window_value);
WWDG_Enable(0x7F); // 初始计数值,必须大于窗口值
// 3. 使能WWDG中断(在超时前N个时钟产生预警中断,给你机会喂狗)
WWDG_EnableIT();
}
void WWDG_IRQHandler(void)
{
// 预警中断:在计数器即将超时前触发
// 这里可以做些紧急处理,然后喂狗
WWDG_SetCounter(0x7F); // 喂狗(重置计数器)
WWDG_ClearFlag();
}
四、实际项目中的看门狗设计策略
我在项目里一般这么设计:
1. 主循环喂狗:在main的while(1)循环里定期调用喂狗函数。如果主循环卡死了,看门狗会复位系统。
2. 关键任务独立看门狗:对于特别关键的任务(比如电机控制),用窗口看门狗监控,确保它在规定时间内执行。
3. 软件看门狗做健康检查:用一个变量记录各模块的状态,主循环定期检查所有模块是否正常。如果某个模块异常,记录错误日志后系统复位。
4. 上电自检:复位后先做硬件自检(RAM测试、外设检测),通过后才正常运行。自检失败就闪灯报警。
五、故障恢复策略
光有看门狗还不够,复位之后怎么办也很重要:
// 检查复位源
uint32_t reset_source = RCC->SR;
if(reset_source & RCC_SR_IWDGRSTF)
{
// 独立看门狗复位
// 清除标志
RCC->SR &= ~RCC_SR_IWDGRSTF;
// 读取Flash里的错误日志,分析原因
// 可以闪红灯报警
}
else if(reset_source & RCC_SR_WWDGRSTF)
{
// 窗口看门狗复位
RCC->SR &= ~RCC_SR_WWDGRSTF;
// 处理...
}
else if(reset_source & RCC_SR_PORSPDRSTF)
{
// 上电复位
// 做初始化...
}
注意
1. 看门狗的超时时间不要设太短。我见过有人设1ms的超时,结果中断优先级高被抢了没时间喂狗就直接复位了。一般设100ms~1s比较合理。
2. 喂狗函数里不要做耗时操作,就是写个寄存器而已,几微秒就完了。
3. 调试的时候可以把看门狗关掉,方便打断点。上线前一定要记得打开。
4. 建议在Flash或EEPROM里存个错误计数器,每次看门狗复位就加1。如果连续复位超过阈值,说明有硬件问题,停止尝试进入安全模式。
5. 最后说一句:看门狗不是万能的。它只能帮你从软件死锁里恢复,解决不了硬件问题。EMC设计、电源滤波、ESD防护这些该做还是要做。
来源: 整理文章为传播相关技术,网络版权归原作者所有,如有侵权,请联系删除。
我要赚赏金
