1.窗口看门狗概述:
(1)之所以称为窗口是因为其喂狗时间是一个有上下限的范围内(窗口),可以通过设定相关寄存器,设定其上限时间(下限时间固定)。喂狗的时间不能过早也不能过晚。而独立看门狗限制喂狗时间在0-x内,x由相关寄存器决定,喂狗时间不能过晚。
(2)窗口看门狗示意图:
(3)窗口看门狗框图:
2.窗口看门狗工作过程总结:
STM32F的窗口看门狗中有一个7位的递减计数器T[6:0],它会在出现下述2中情况之一产生看门狗复位:
- 当喂狗的时候如果计数器的值大于某一设定数值W[6:0]时,此设定数值在WWDG_CFR寄存器定义。
- 当计数器的数值从0x40减到0x3F时[T6位跳变到0]。
- 如果启动了看门狗并且运行中断,当递减计数器等于0x40时,产生早期唤醒中断(EWI),它可以用于喂狗以避免WWDG复位。
3.窗口看门狗超时时间计算:
4.窗口看门狗的必要性:
对于一般的看门狗,程序可以在它产生复位前的任意时刻刷新看门狗,但这存在的隐患是有可能程序跑乱了又跑回到正常的地方,或跑乱的程序正好执行了刷新看门狗操作,这样的情况下一般的看门狗就检测不出来。如果使用窗口看门狗,程序员可以根据程序正常执行的时间设置刷新看门狗的一个时间窗口,这样可以检测出程序没有按照正常的路径运行非正常地跳过了某些程序段的情况。
5.窗口看门狗注意事项:
- 上窗口值W[6:0]必须大于下窗口值0x40,否则就无窗口。
- 窗口看门狗时钟来源PCLK1(APB1总线时钟)分频后。
6.窗口看门狗常用寄存器:
- 控制寄存器WWDG_CR;
- 配置寄存器WWDG_CFR;
- 状态寄存器WWDG_SR;
7.窗口看门狗的一般配置步骤:
- 使能看门狗时钟:RCC_APB1PeriphClockCmd();
- 设置分频系数:WWDG_SetPrescaler();
- 设置上窗口值:WWDG_SetWindowValue();
- 开启提前唤醒中断并分组(可选):WWDG_EnableIT() NVIC_Init();
- 使能看门狗:WWDG_Enable();
- 喂狗:WWDG_SetCounter();
- 编写中断服务函数:WWDG_IRQHandler();
8.窗口看门狗实验:
当没有进行喂狗时,该程序就不停的复位,就不停的执行主函数;若在有效时间范围内,不停的喂狗,该程序就不会复位。
(1)主函数:
#include "delay.h"
#include "led.h"
#include "wwdg.h"
int main(){
delay_init(); //延时初始化
LED_Init(); //LED初始化
WWDG_Init(0x7F,0x5F,WWDG_Prescaler_8); //窗口看门狗初始化
delay_ms(500);
while(1){
}
}
(2)头文件:
#ifndef __WWDG_H
#define __WWDG_H
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
void WWDG_Init(u8 tr,u8 wr,u32 fprer); //窗口看门狗初始化
void WWDG_Set_Counter(u8 cnt); //重置计数器的值
void WWDG_NVIC_Init(void); //窗口看门狗中断管理
#endif
(3)窗口看门狗功能初始化:
#include "stm32f10x.h"
#include "wwdg.h"
#include "delay.h"
u8 WWDG_CNT=0x7F; //保存WWDG计数器的设置值,默认为最大
/*
功能:窗口看门狗初始化
变量:tr:计数器值 wr:窗口值 fprer:分频系数 Fwwdg=PLCKL/(4096/2^fprer)
返回值:无
*/
void WWDG_Init(u8 tr,u8 wr,u32 fprer)
{
//1.使能WWDG时钟
RCC_APB2PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
//2.初始化WWDG_CNT(将tr的最高位设置为0,其他位保持不变)
WWDG_CNT=tr&WWDG_CNT;
//3.设置WWDG预分频系数
WWDG_SetPrescaler(fprer);
//4.设置窗口值
WWDG_SetWindowValue(wr);
//5.使能看门狗
WWDG_Enable(WWDG_CNT);
//6.清除提前唤醒标志
WWDG_ClearFlag();
//7.设置中断服务函数
WWDG_NVIC_Init();
//8.开启窗口看门狗中断
WWDG_EnableIT();
}
/*
功能:重新设置WWDG计数器值
变量:cnt:设置的计数器值
返回值:无
*/
void WWDG_Set_Counter(u8 cnt)
{
WWDG_Enable(cnt);
}
/*
功能:中断函数
变量:无
返回值:无
*/
void WWDG_NVIC_Init(void)
{
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel=WWDG_IRQn; //中断通道->窗口看门狗中断通道
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; //使能
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2; //抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority=2; //子优先级
NVIC_Init(&NVIC_InitStruct);
}
/*
功能:中断函数
变量:无
返回值:无
*/
void WWDG_IRQHandler(void)
{
WWDG_SetCounter(WWDG_CNT); //提醒喂狗
WWDG_ClearFlag(); //清除中断唤醒标志
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
delay_ms(20);
GPIO_SetBits(GPIOB,GPIO_Pin_5);
}