看门狗
一个能够定时产生复位信号的计数器,主要用于检测设备在实际情况下由于受到外界干扰而程序跑飞进入死循环。
基本原理:向下递减计数——重装载(喂狗)——重新计数 (正常喂狗,程序在正常运行)
向下递减计数——不触发重装载(不喂狗)——计数递减到底——触发复位信号 (没有按时喂狗,说明程序发生异常,触发复位重启程序)
看门狗分类
独立看门狗(IWDG)
独立看门狗运行在主程序之外,由专门时钟LSI(低速内部时钟)提供(主程序发生错误的时候玩意主程序时钟失效的情况下,IWDG在主程序外仍能够正常工作)
因此其特点为精度较低,运行在主程序之外独立工作。只有当递减到0的时候才会触发复位信号
窗口看门狗(WWDG)
窗口看门狗由APB1时钟分频作为时钟提供,通过编程配置来检测应用程序是否过早/迟操作,其要求在某个计数区间内喂狗。如果没到区间喂狗/超出区间都会触发复位信号。同时在即将超出区间触发复位之前,可以开启提前唤醒中断(EWI)在复位前进行数据保存等抢救工作。这是独立看门狗所没有的功能。
WWDG中只有上限是可以配置的,下限是固定的。固定以0X3F(63)处为下限,固定在0X40(64)处可开启EWI。
CUBEMX配置
IWDG
IWDG处开启,设置预分频系数为16分频,向下计数重装载计数值为4096(实际计数值为4095-0共4096个数)。
超时时间计数
Tout=((4×2^PRER) ×RLR)/LSI时钟频率
其中4×2^PRER为分频系数PSC,最低为4,总体PSC大小由实际寄存器中PR的值控制,CUBEMX中配置所设置的直接就是PSC,无需自己配置PR计算。在LSI提供的时钟下,分频越大,重装载值越大,超时触发复位的时间就越长。
LSI在32kHz下,此时超时时间即为2s左右
WWDG
第一项为PSC(计算同理,不过用的是APB1时钟)
第二项为上窗口值,要求填入数在64-127之间且不大于第三项计数初始值
第三项技术初始值,要求填入数在64-127之间
第四项选择是否开启EWI
开启完EWI后别忘了打开对应中断并对中断优先级进行合理配置
超时时间计算:PCLK1本身为42MHz经过4096分频和预分频8分频后单次计数时间为0.78ms左右,127计数到95后进入复位上限范围内,共计数32次,用时约25ms。计数到ESI即64时共计数63次,用时约49.15ms。若无ESI,计数到下限64时共计数64次,用时约50ms。
代码部分
配置好后,程序已经自动初始化好了IWDG和WWDG
进入MX_IWDG_Init内部定义可以看到其为我们配置好了IWDG的预分频系数和重装载值,传入句柄入初始化函数并检查是否正确初始化,MX_WWDG_Init同理
喂狗函数
HAL_IWDG_Refresh(&hiwdg);
HAL_WWDG_Refresh(hwwdg);
在主程序中合理喂狗即可。
验证IWDG,在单片机上电后进入while前,设置LED点亮,进入while后适当延时后将LED熄灭(适当延时为了方便肉眼观察LED),后进行长延时使得IWDG超时。
HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_RESET);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay(1200);
HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_SET);
HAL_Delay(4000);
}
/* USER CODE END 3 */
}
实际效果为LED在闪烁,说明由于没有喂狗系统在不断触发复位。且复位周期符合我们在CUBEMX处预设的2s左右。
同理,在熄灭LED后进行喂狗,则IWDG就不会触发复位。
HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_RESET);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay(1200);
HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_SET);
HAL_IWDG_Refresh(&hiwdg);
}
实际效果为单片机上电后LED亮起,然后熄灭后保持熄灭再也没有亮起。
总结:基本思路为将熄灭LED处代码换成正常需要监控的代码,如果代码跑飞,出bug无法正常进入喂狗函数,就会触发复位。
下面用WWDG配合EWI实现LED延时反转。
思路:开启WWDG的EWI,设计计数初始值计数到复位触发值的时间为所需的延时时间,主程序中不进行喂狗。在复位前利用EWI进入中断,在中断中喂狗并翻转LED电平实现计时功能。
根据先前计算,进入ESI的时间为约50ms,则LED翻转频率将为20Hz。
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef* hwwdg)
进行EWI回调函数重写,在其中实现喂狗并翻转电平
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef* hwwdg)
{
HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);
HAL_WWDG_Refresh(hwwdg);
}
实现效果为PF10对应LED快速闪烁。