窗口看门狗
窗口看门狗概述
之所以称为窗口看门狗就是因为其喂狗时间是一个有上下限的范围内(窗口),你可以通过设定相关寄存器,设定其上限时间(下限固定)。
喂狗的时间不能过早也不能过晚。
而独立看门狗限制喂狗时间在0-x内,x由相关寄存器决定。0就相当于刚开始倒计数就喂狗,x就相当于快要计数到0时喂狗,喂狗的时间不能过晚。
窗口看门狗框图
窗口看门狗简易说明图
窗口看门狗时序图
窗口看门狗工作过程总结
STM32F的窗口看门狗中有一个7位的递减计数器T[6:0],它会在出现下述2种情况之一时产生看门狗复位:
1.当喂狗的时候如果计数器的值大于某一设定数值W[6:0]时,此设定数值在WWDG_CFR寄存器定义。
2.当计数器的数值从0x40减到0x3F时(T6位跳变到0)
如果启动了看门狗并且允许中断,当递减计数器等于0x40时产生早期唤醒中断(EWI),它可以用于喂狗以避免WWDG复位。
窗口看门狗时间计算
Twwdg:WWDG超时时间(单位为ms)
WDGTB:WWDG的预分频系数,是以2为底数的,公式计算中如果WDGTB为3,则23 = 8
T[5:0]:窗口看门狗的计数器低6位
为什么公式是T[5:0]+1呢?
原因:T[5:0]表示6位数,因为WWDG_CR 寄存器是6位计数的,即可以从111 1111一直递减到100 0000,这期间的计数值就用T[5:0]来表示,而100 0000 = 0x40,计数值到0x40时还没有产生复位,还要再减一次到0x3F才产生复位,所以计数值一共是T[5:0]+1次
写入 WWDG_CR 寄存器的值
应用程序在正常运行过程中必须定期地写入WWDG_CR寄存器以防止MCU发生复位。只有当计数器值小于窗口寄存器的值时,才能进行写操作。储存在WWDG_CR寄存器中的数值必须在 0xFF 和 0xC0之间
为什么WWDG_CR寄存器的值必须在 0xFF 和 0xC0之间内?
原因:0xFF = 1111 1111,0xC0 = 1100 0000 ,因为窗口看门狗是根据WWDG_CR寄存器的第6位来判断是否产生复位的,如果T6从1变为了0,就产生了复位,所以在写入WWDG_CR寄存器时要保证T6为1,剩下的T0 ~ T5就可用来设定值
在手册中也有说明T6要置为1
注意
计数值0x40,0x3F是对WWDG_CR 寄存器的低6位来说的,即T5 ~ T0,T6就是0x40和0x3F的分界线,T6为1,则计数值大于0x40,T6为0,则计数值小于或等于0x3F
而在程序中写WWDG_CR 寄存器时,是8位都要写进去的,最高位T7使能窗口看门狗,固定为1,剩下的T6到T0就作为计数值
为什么要窗口看门狗?
对于一般的看门狗,程序可以在它产生复位前的任意时刻刷新看门狗,但这有一个隐患,有可能程序跑乱了又跑回到正常的地方,或跑乱的程序正好执行了刷新看门狗操作,这样的情况下一般的看门狗就检测不出来了;
如果使用窗口看门狗,程序员可以根据程序正常执行的时间设置刷新看门狗的一个时间窗口,保证不会提前刷新看门狗也不会滞后刷新看门狗,这样可以检测出程序没有按照正常的路径运行非正常地跳过了某些程序段的情况。
窗口看门狗其他注意事项
1.上窗口值W[6:0]必须大于下窗口值0x40,否则就无窗口了
2.窗口看门狗时钟来源PCLK1 (APB1总线时钟)分频后。
窗口看门狗相关寄存器和库函数
void WWDG_Enable(uint8_t Counter); //启动并设置初始值
void WWDG_SetCounter(uint8_t Counter); //喂狗
void WWDG_EnableIT(void); //使能提前唤醒中断
void WWDG_SetPrescaler(uint32_t WWDG_Prescaler); //设置预分频系数
void WWDG_SetWindowValue(uint8_t WindowValue); //设置窗口值
FlagStatus WWDG_GetFlagStatus(void);
void WWDG_ClearFlag(void);
窗口看门狗配置过程
1.使能看门狗时钟:
RCC_APB1PeriphClockCmd();
2.设置分频系数:
WWDG_SetPrescaler();
3.设置上窗口值:
WWDG_SetWindowValue();
4.开启提前唤醒中断并分组(可选):
WWDG_EnableIT();
NVIC_Init();
5.使能看门狗:
WWDG_Enable();
6.喂狗:
WWDG_SetCounter();
7.编写中断服务函数
WWDG_IRQHandler();
窗口看门狗初始化代码
u8 WWDG_CNT = 0x7F;
/**
* @name WWDG_Init
* @brief 窗口看门狗初始化
* @param tr:T[6:0],计数器值
* wr:W[6:0],窗口值
* fprer:分频系数(WDGTB),仅最低2位有效
* @retval None
*/
void WWDG_Init(u8 tr,u8 wr,u32 fprer)
{
//使能窗口看门狗时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
//设置预分频系数
WWDG_SetPrescaler(fprer);
//设置上窗口的值
WWDG_SetWindowValue(wr);
/*因为传入WWDG_Enable函数的参数是T[6:0]的值,只有7位有效,但形参tr是8位的,
所以,要用一个变量来取出低7位,再传入Enable函数使能看门狗*/
WWDG_CNT = tr & WWDG_CNT;
//使能看门狗,设置counter
WWDG_Enable(WWDG_CNT);
//清除提前唤醒中断标志位
WWDG_ClearFlag();
//初始化窗口看门狗NVIC
WWDG_NVIC_Init();
//开启窗口看门狗中断
WWDG_EnableIT();
}
/**
* @name WWDG_NVIC_Init
* @brief 窗口看门狗NVIC初始化
* @param None
* @retval None
*/
void WWDG_NVIC_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_Init(&NVIC_InitStructure);
}
/**
* @name WWDG_IRQHandler
* @brief 窗口看门狗中断处理函数
* @param None
* @retval None
*/
void WWDG_IRQHandler(void)
{
WWDG_SetCounter(WWDG_CNT); //喂狗操作,当禁掉此句后,窗口看门狗将产生复位
WWDG_ClearFlag(); //清除提前唤醒中断标志位
}
main函数
int main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //NVIC初始化分组
LED_Init(); //LED初始化
delay_init(); //延时初始化
KEY_Init(); //按键初始化
//EXTIx_Init(); //外部中断初始化
//USART1_Init(9600); //串口初始化
//IWDG_Init(); //独立看门狗初始化
delay_ms(500); //延时500ms
/*窗口看门狗初始化后,在中断处理函数中进行了喂狗操作,所以不会产生复位,LED灯一直被点亮
如果中断处理函数中去掉了喂狗操作,则倒计数到0x3F后会产生复位,LED灯不断闪烁*/
WWDG_Init(0x7F,0x5F,WWDG_Prescaler_8); //窗口看门狗初始化
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
while(1)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_1); //点亮LED
}
}
窗口看门狗和独立看门狗的对比
1.使用条件对比
2.特点对比
3.两者区别
独立看门狗与窗口看门狗的区别如下:
-
独立看门狗没有中断,窗口看门狗有中断。
-
独立看门狗有硬件软件之分,窗口看门狗只能软件控制。
-
独立看门狗只有下限,窗口看门狗有下限和上限。
-
独立看门狗是12位递减的,窗口看门狗是7位递减的。
-
独立看门狗是用的内部大约40KHz的RC振荡器,窗口看门狗是用的系统时钟APB1ENR
独立看门狗没有中断功能,只要在计数器减到0(下限)之前,重新装载计数器的值,就不会产生复位。
要注意看门狗和外接复位IC同时存在的情况,外部电路可能会阻止看门狗复位。
窗口看门狗有中断,这个中断的作用是在计数器达到下限0x40的时候,产生中断,让你喂狗;如果你不喂狗,计数器的值变为0x3f的时候,将会产生系统复位;即使是喂狗,也应该在中断里快速喂狗,要不时间长了计数器减1也会变成0x3f产生复位。
窗口看门狗还有一个上限值,这个值如果大于计数器的初始值,那么就没有任何作用了;这个值小于计数器初始值的时候,当计数器的值大于上限值时你对计数器进行装载,将会产生复位,只有在计数器减到小于上限值时,你才能重新装载计数器。意思就是说只有计数器的值在上限值和下限值之间你才能装载计数器,否则就会产生系统复位,当上限值小于下限值,也没有意义。