STM32F103ZET6窗口看门狗
1、WWDG简介
窗口看门狗(WWDG)通常被用来检测由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。
WWDG是一个不断往下递减的计数器。当WWDG的计数器递减到固定值0x40时,还没有重新赋值计数值(俗称喂狗),就会产生一个复位信号,使芯片复位,这个0x40的固定值就叫做窗口的下限值,窗口下限值不需要设置。
WWDG还有一个窗口上限值,当WWDG的计数器的值大于窗口上限值的时候,如果给WWDG的计数器重新赋值(喂狗),也会产生一个复位信号,使芯片复位,窗口的上限值可以通过程序设置。
也就是说在使用WWDG的时候,给WWDG的计数器重新赋值不能够太早,也不能够太晚,必须在一定时间之内。
2、WWDG的时间计算
WWDG是挂载在APB1总线上的外设,所以WWDG的时钟源来自PCLK1。需要注意的是PCLK1在给WWDG提供时钟源的时候已经被4096分频了,这个分频是芯片默认的,没办法更改。所以WWDG时钟的时钟源应该是PCLK1/4096。
由于WWDG不像IWDG一样有独立的时钟源,在使用WWDG的时候,需要先使能WWDG的时钟,否则无法使用。
WWDG的时钟可以被分频,通过配置WWDG_CFR配置寄存器的BIT8~BIT7位的WDGTB[1:0]可以对来自PCLK1/4096的时钟进行分频,如下:
- WDGTB[1:0] = 00:WWDG的计数器时钟来自PCLK1/4096后再除以1。
- WDGTB[1:0] = 01:WWDG的计数器时钟来自PCLK1/4096后再除以2。
- WDGTB[1:0] = 10:WWDG的计数器时钟来自PCLK1/4096后再除以4。
- WDGTB[1:0] = 11:WWDG的计数器时钟来自PCLK1/4096后再除以8。
所以WWDG的时钟计算公式如下:
WWDG_CLK = PCLK1/(4096*PR)
PCLK1是APB1总线时钟,PR是WWDG的分频系数。
得出WWDG的时钟大小之后,就可以算出WWDG的计数器每递减一次所经过的时间,如下:
Step_time = 1/WWDG_CLK = (4096*PR)/PCLK1
如果PCLK1的单位为MHZ,那么计算出来的单位就是us级;如果PCLK1的单位为KHZ,那么计算出来的单位就是ms级。
假设PCLK1 = 36MHZ,那么WWDG的最小超时时间为:
-
- 当WDGTB = 0时,WWDG的最小超时时间为:time = (4096*1)/36(us) = 113(us)。
- 当WDGTB = 1时,WWDG的最小超时时间为:time = (4096*2)/36(us) = 227(us)。
- 当WDGTB = 2时,WWDG的最小超时时间为:time = (4096*4)/36(us) = 455(us)。
- 当WDGTB = 3时,WWDG的最小超时时间为:time = (4096*8)/36(us) = 910(us)。
得出WWDG计数器每递减一次所经过的时间后,还需要根据WWDG计数器的初值和固定值0x40计算WWDG计数器的递减次数。假设初值设置为X,那么WWDG产生复位信号的时间计算如下:
Twwdg = ((4096*PR)/PCLK1)*(X - 0x40)
3、WWDG的窗口值
WWDG计数器的值必须在一个范围内才可以重新赋值,这个范围又窗口上限值和窗口下限值组成。
WWDG的窗口下限值是一个固定值,该值固定位0x40。
WWDG的窗口上限值是由WWDG_CFR配置寄存器的BIT6~BIT0位组成。WWDG的窗口上限值必须大于固定值0x40,如果小于等于固定值0x40就失去了窗口的价值,而且也不能大于计数器的值,由于WDG计数器的最大值为0x7F,所以WWDG的窗口上限值必须小于0x7F。
在实际使用中,一般使用WWDG的中断功能,在中断服务函数中对WWDG进行喂狗。如果开启了WWDG的中断功能,当WWDG的计数器逐渐递减到0x40的时候就会产生中断,在中断服务函数内对WWDG的计数器重新赋值。如果WWDG的计数器递减到0x3F时,WWDG的计数器还没有重新赋值,那么就会产生复位。
3、WWDG配置流程
在使用WWDG之前,必须先使能WWDG的时钟,否者无法使用WWDG的功能。
通过WWDG_CFR配置寄存器设置WWDG的时钟分频系数、窗口上限值、中断启动。
通过WWDG_CR控制寄存器设置WWDG的使能、计数器初值。
通过NVIC配置WWDG的中断分组、优先级、中断使能。
编写中断服务函数进行喂狗操作。
4、HAL库操作WWDG
初始化代码如下:
WWDG_HandleTypeDef WWDG_Handle_Init;
void WWDG_Init(void)
{
__HAL_RCC_WWDG_CLK_ENABLE();
WWDG_Handle_Init.Instance = WWDG;
WWDG_Handle_Init.Init.Prescaler = WWDG_PRESCALER_8;
WWDG_Handle_Init.Init.Counter = 0x7F;
WWDG_Handle_Init.Init.Window = 0x5F;
WWDG_Handle_Init.Init.EWIMode = WWDG_EWI_ENABLE;
HAL_WWDG_Init(&WWDG_Handle_Init);
HAL_NVIC_SetPriority(WWDG_IRQn,2,1);
HAL_NVIC_EnableIRQ(WWDG_IRQn);
}
首先定义一个WWDG的句柄结构体变量,该变量是一个全局变量。
通过HAL_WWDG_Init函数对WWDG进行初始化,设置分频系数、计数器初值、窗口上限值,开启中断。
通过HAL_NVIC_SetPriority函数设置WWDG的中断优先级。
通过HAL_NVIC_EnableIRQ函数使能WWDG的中断功能。
WWDG中断服务函数如下:
void WWDG_IRQHandler(void )
{
HAL_WWDG_IRQHandler(&WWDG_Handle_Init);
}
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{
HAL_WWDG_Refresh(&WWDG_Handle_Init);
}
HAL_WWDG_EarlyWakeupCallback是WWDG的回调函数,在HAL_WWDG_IRQHandler函数中调用。
通过HAL_WWDG_Refresh函数对WWDG的计数器进行重新赋值。