窗口看门狗(WWDG)通常被用来监测由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。除非递减计数器的值在T6位(WWDG->CR的第六位)变成0前被刷新,看门狗电路在达到预置的时间周期时,会产生一个MCU复位。在递减计数器达到窗口配置寄存器(WWDG->CFR)数值之前,如果7位的递减计数器数值(在控制寄存器中)被刷新,那么也将产生一个MCU复位。
窗口看门狗实验:开启STM32的窗口看门狗,并使能唤醒中断。主程序正常运行时喂狗,用按键中断模拟程序故障死机,此时将触发唤醒中断并产生复位,用LED灯指示唤醒中断的触发。
(1)打开串口,使用异步通信模式
(2)PE2设置为Output,用于指示唤醒中断产生的现象
(3)设置PA0为外部中断EXTIO,模拟故障死机
(4)设置时钟为外部时钟
(5)设置窗口看门狗
(6)设置定时器中断
注意:窗口看门狗的中断优先级要比外部中断的优先级高
主函数程序:
uint8_t wr, tr; //wr上窗口的值,tr当前计数器的值
printf("this is WWDG test\n"); //打印程序复位时的调试代码
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_SET); //先熄灭LED灯
wr = WWDG->CFR & 0x7f; //获取我们设置的上窗口的值
while (1)
{
tr = WWDG->CR & 0x7f; //获取当前计数器的值
if(tr < wr) //计数器的值小于上窗口的值时,自动进行喂狗
{
HAL_WWDG_Refresh(&hwwdg); //喂狗操作(本质上:更新我们设置的递减计数器的值)
}
}
按键按下时,外部中断函数:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_0)
{
printf("程序故障\n");
while(1); //模拟故障死机
}
}
当计数器的值小于0X4F时(下窗口的值),系统提前唤醒并触发中断,程序如下:
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg) //提前唤醒中断
{
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_RESET); //点亮LED灯
printf("EarlyWakeup int\n");
}
总结:
(1)窗口看门狗的计数器是一个递减计数器,共有 7 位,其值存在控制寄存器 CR 的位 6:0,即 T[6:0],当 7 个位全部为 1时是 0X7F,这个是最大值,
(2)当递减到 T6 位变成 0时,即从0X40 变为 0X3F时候,会产生看门狗复位。这个值 0X40 是看门狗能够递减到的最小值,
(3)当递减计数器递减到 0X40 的时候,还不会马上产生复位,如果使能了提前唤醒中断:CFR 位 9 EWI 置 1,则产生提前唤醒中断,如果真进入了这个中断的话,就说明程序肯定是出问题了,
(4)那么在提前唤醒中断的处理程序中我们就需要做最重要的工作,比如保存重要数据,或者报警等,这个中断我们也叫它死前中断。