STM32的窗口看门狗的主要功能是,程序过早的喂狗还有太晚喂狗,都会触发单片机重启,就是有一个时间段,在这个时间段内喂狗才不会触发单片机重启。
下面我就总结一下窗口看门狗的设置过程:
第一步:开启窗口看门狗APB1的时钟
第二步:配置各个寄存器(预分频器和窗口值)
WWDG_SetPrescaler()写入预分频器
WWDG_SetWindowValue()写入窗口值
第三步:写入控制寄存器CR(看门狗是能位,计数器溢出标志位和计数器有效位)
第四步:喂狗 WWDG_SetCounter()
主要的步骤就是这么多了,其他的程序自己搞定,在程序中加入上面的四步就能实现窗口看门狗

WWDG_SetPrescaler()写入预分频器的函数,下面截图是这个函数的具体操作:

WWDG_SetWindowValue()写入窗口值的函数,下面截图是这个函数的具体操作:

WWDG_Enable() 使能窗口看门狗,下面截图是这个函数的具体操作:

WWDG_SetCounter() 喂狗函数,下面截图是这个函数的具体操作:

下面就是我写的一个小例子了:

其实我看来整体过程还是比较简单的,最复杂的一点就是第二步中的预分频器和窗口值的计算,下面我们来分析一下过程:

超时时间:50ms = 1/36000(PCLK1是36M) X 4096 X 第三个预分频系数 X T(0到5位)+1

APB1的时钟频率:

50ms = 1/36000 X 4096 X 8 X (T[5:0] + 1)
50ms = 0.9102222222 X(T[5:0] + 1)
(T[5:0] + 1) = 50 / 0.910222222
(T[5:0] + 1) = 54.9316406263411
取整:(T[5:0] + 1) = 55
T[5:0] = 54

上面这是最大值的计算,下面是最小值的计算,也就是最小的喂狗时间计算:

比如说我定的最小的喂狗时间为30ms
30ms = 1 / 36000 X 4096 X 8 X (T[5:0] - W[5:0])
30ms = 0.910222222 X(T[5:0] - W[5:0])
(T[5:0] - W[5:0]) = 30ms / 0.9102222222
T[5:0] - W[5:0] = 32.95898 (取整33)
T[5:0] - W[5:0] = 33 前面算的T[5:0] = 54
54 - W[5:0] = 33
W[5:0] = 21

至此所需要最长和最短的喂狗时间都计算完了,可以编程了,下面就是主要的main函数:
cs
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "Delay.h"
#include "Key.h"
int main(void)
{
OLED_Init(); //oled 屏幕初始化
Key_Init();
/*
第一步:开启窗口看门狗APB1的时钟
第二步:配置各个寄存器(预分频器和窗口值)
WWDG_SetPrescaler()写入预分频器
WWDG_SetWindowValue()写入窗口值
第三步:写入控制寄存器CR(看门狗是能位,计数器溢出标志位和计数器有效位)
第四步:喂狗 WWDG_SetCounter()
*/
OLED_ShowString(1,1,"WWDG Reset");
if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST) == SET) //如果(RCC读看门狗复位标志位为1)
{
OLED_ShowString(2,1,"WWDG RST"); // 显示:IWDG RST
Delay_ms(500); // 等待500毫秒
OLED_ShowString(2,1," "); // 显示:空格
Delay_ms(500); // 等待500毫秒
RCC_ClearFlag(); //清除看门狗复位标志位
}
else //否则:
{
OLED_ShowString(3,1,"RST"); // 显示:RST
Delay_ms(500); // 等待500毫秒
OLED_ShowString(3,1," "); // 显示:空格
Delay_ms(500); // 等待500毫秒
}
//第一步:开启窗口看门狗APB1的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
//第二步:配置各个寄存器(预分频器和窗口值)
// WWDG_SetPrescaler()写入预分频器
// WWDG_SetWindowValue()写入窗口值
WWDG_SetPrescaler(WWDG_Prescaler_8);
WWDG_SetWindowValue(0x40 | 21); // 30ms
WWDG_Enable(0x40 | 54); //50ms
while(1)
{
Key_GetValue();
//第四步:喂狗 WWDG_SetCounter()
Delay_ms(31); //这个延时过长就会触发看门狗复位
WWDG_SetCounter(0x40 | 54);
}
}
上面的程序喂狗时间如果低于30ms和高于50毫秒,都会触发窗口看门狗复位,单片机都会自动重启,为了不叫单片机自动重启,请在合理的时间内进行喂狗操作。