定义
看门狗的实质是一个定时器,在启动后,须要在肯定工夫内再给它一个信号,俗称“喂狗”,如果没有按时“喂狗”,阐明 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");
}