定义
看门狗的本质是一个定时器,在启动后,需要在一定时间内再给它一个信号,俗称“喂狗”,如果没有按时“喂狗”,说明MCU可能处于非正常状态,这时看门狗就向MCU发送个复位信号,使整个系统重启,重新进入正常的工作状态。看门狗命令在程序的中断中拥有最高的优先级。
独立看门狗( Independent Watchdog, IWDG)
时钟:独立看门狗的时钟源来自LSI(内部低速时钟),意味着不受外部晶振电路影响,同时就算系统主时钟发生故障时,也可以正常工作。使用内部晶振,也意味精度并不高,因此只适合应用在对时间精度要求比较低的场合。
计数:独立看门狗的计数器是一个12位的递减计数器,计数最大值为0xFFF,当计数器递减到0时,就会产生一个复位信号,重启整个系统。如果在递减到0之前,将重装载数值写入递减计数器,就会由重装载数值开始递减到0,如此反复,就永远不会到0,就不会产生复位信号,这个重装载计数值写入递减计数器的过程就叫“喂狗”。
重装载数值来自重装载寄存器( IWDG_RLR), 这个值大小决定独立看门狗的溢出时间(复位倒计时)。
/*
* STM32
* 函数名: void IWDG_Init(uint16_t period)
* 输入参数: period-设置喂狗周期,单位 ms
* 输出参数:无
* 返回值:无
* 函数作用:初始化独立看门狗的喂狗时间
* 刷新时间计算: Prescaler/LSI*Reload
*/
void IWDG_Init(uint16_t period) {
hiwdg.Instance = IWDG; // 选择独立看门狗
hiwdg.Init.Prescaler = IWDG_PRESCALER_256; // 设置预分频
hiwdg.Init.Reload = 40000/256*period/1000; // 设置重装载值
if (HAL_IWDG_Init(&hiwdg) != HAL_OK) // 初始化独立看门狗
{
Error_Handler();
}
}
总结:独立看门狗包含一个12位递减计数器,从用户定义的t开始递减到0,必须在t~0之间喂狗,否则复位重启。
窗口看门狗( Windowwatchdog, WWDG)
窗口看门狗,包含一个7位递减计数器,从用户定义的t开始递减到64,必须在t~64之间喂狗,在t之前或者64之后喂狗,也会导致复位重启。 这里的t值,称之为窗口上限,由用户自定义设置;这里的64,称之为窗口下限,是系统固定的。窗口看门狗计数器必须在上窗口和下窗口之间被刷新(喂狗),不能过早,也不能过晚,这也就窗口看门狗中的“窗口”含义。
时钟:窗口看门狗的时钟源来自PCLK1(最高36MHz),经过4096分频,再经过WWDG_CFG的Bits[8:7]位WDGTB分频得到, WDGTB支持2^n分频( 0≤n≤3)。
计数: 窗口看门狗的计数器是一个7位的递减计数器,计数最大值为0x7F,当计数器递减到0x3F时,就会产生一个复位信号,重启整个系统。 当递减计数器递减到0x40时,如果使能了提前唤醒中断( WWDG_CFG的Bits[9]位EWI设置为1), 则会产生提前唤醒中断,在该中断可以保存重要数据或者向WWDG_CR重新写入新计数器值,完成喂狗操作。 一旦0x40变为0x39,系统将进行复位,因此必须在一个窗口看门狗计数周期内完成喂狗操作。WWDG_CR的Bits[7]位WDGA为窗口看门狗使能位,当为1时,窗口看门狗才工作。
窗口:窗口看门狗的WWDG_CFG的Bits[6:0]位为窗口上边界值,该值应小于计数器最大值0x7F,大于窗口下边界值0x3F。
窗口看门狗初始化
“HAL_WWDG_Init()–HAL库系统函数”函数会回调“ HAL_WWDG_MspInit()–HAL库系统函数”进行硬件相关初始化。
窗口看门狗中断处理
使能中断后,当窗口看门狗计数到0x40时,会进去提前唤醒中断,在该中断处理函数里,用户可以保存数据或喂狗。
/*
* 函数名: void WWDG_IRQHandler(void)
* 输入参数:无
* 输出参数:无
* 返回值:无
* 函数作用: WWDG 的中断处理函数
*/
void WWDG_IRQHandler(void) {
HAL_WWDG_IRQHandler(&hwwdg); // HAL库的系统函数
}
/*
* 函数名: void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef* hwwdg)
* 输入参数: hwwdg-WWDG 句柄
* 输出参数:无
* 返回值:无
* 函数作用:提前唤醒中断回调函数
*/
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef* hwwdg) {
ClearWWDG(); // 用户函数内调用HAL库的系统函数“ HAL_WWDG_Refresh()”刷新计数器值,实现喂狗操作
printf("-------复位前保存数据------\n\r");
printf("--------- 软件喂狗 --------\n\r");
}
对比