窗口看门狗—WWDG
1.基本介绍
独立看门狗是12位递减计数器,窗口看门狗是7位递减计数器。
独立看门狗没上限值,窗口看门狗有上限值(由用户设定)和固定下限值(0X40)。
窗口看门狗在上限值以上进行喂狗会产生复位,在下限值还未进行喂狗也会产生复位。故窗口看门狗一定要在上限值和下限值之间进行喂狗。
1.1窗口看门狗时钟
窗口看门狗时钟来自PCLK1,挂接在APB1总线上,由RCC开启。最大频率为42M。
1.2WDG预分频器
PCLK1时钟经过预分频器分频后输入给计数器时钟。
分频因子通过WWDG_CFR的8:7设置分频因子,可设为0 、 1 、 2、 3。
分频后的计数器时钟为:CK_CNT=PCLK1/4096/(2^WDGTB)
PCLK1等于APB1时钟;
WDGTB为分频因子(0-3)
4096为固定值。
1.3计数器
计数器为7位递减计数器,故计数器最大值为0x7F。值放在WWDG_CR中的6:0位。故计数器的范围为0x7F-0x40。
为防止忘记进行喂狗,可开启提前唤醒中断。开启后当计数器计数到0x40时,进入中断。开启中断方式为WWDG_CFR位9EWI置1。
如果不用中断进行喂狗,也可以进行计算,在计算时间内进行喂狗。
Twwdg=(4096×2^WDGTB×(T[5:0]+1))/PCLK1;
Twwdg为窗口看门狗的超时时间,单位为ms。
PCLK1为APB1的时钟频率,最大42MHz。
WDGTB为窗口看门狗的预分频系数。
T[5:0]为窗口看门狗的计数器低6位。
若PCLK1为42MHz,则最大超时和最小超时时间如下图
1.4看门狗配置寄存器(WWDG_CFR)
一般设置为窗口看门狗时间比实际程序运行时间稍大一些,就可在程序刚运行完后进行看门狗喂狗。
1.5系统复位信号
当超过窗口上限值喂狗或低于窗口下限值还未进行喂狗,并且WDGA位置为1(开启窗口看门狗)。将产生一个复位信号,系统复位。
2.相关寄存器
2.1中断结构体
typedef struct
{
uint8_t NVIC_IRQChannel;//中断通道
uint8_t NVIC_IRQChannelPreemptionPriority;//抢占优先级
uint8_t NVIC_IRQChannelSubPriority;//子优先级
FunctionalState NVIC_IRQChannelCmd;//中断使能
} NVIC_InitTypeDef;
2.2窗口看门狗结构体
typedef struct
{
__IO uint32_t CR; //看门狗控制寄存器,设置计数值及使能看门狗
__IO uint32_t CFR; //看门狗配置寄存器,设置窗口值上限,使能中断
__IO uint32_t SR; //状态寄存器,清除中断标志位
} WWDG_TypeDef;
3.配置步骤
3.1分步设置
(1)定义相关结构体
(2)开启开门狗时钟
(3)设置窗口值和分频数
WWDG_SetWindowValue(0x5f);//设置窗口值
WWDG_SetPrescaler(WWDG_Prescaler_8);//设置分频值
//设定窗口值
void WWDG_SetWindowValue(uint8_t WindowValue)
{
__IO uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_WWDG_WINDOW_VALUE(WindowValue));
/* Clear W[6:0] bits */
tmpreg = WWDG->CFR & CFR_W_MASK;
/* Set W[6:0] bits according to WindowValue value */
tmpreg |= WindowValue & (uint32_t) BIT_MASK;
/* Store the new value */
WWDG->CFR = tmpreg;
}
#define WWDG_Prescaler_1 ((uint32_t)0x00000000)
#define WWDG_Prescaler_2 ((uint32_t)0x00000080)
#define WWDG_Prescaler_4 ((uint32_t)0x00000100)
#define WWDG_Prescaler_8 ((uint32_t)0x00000180)
//设置分频数
/**
* @brief Sets the WWDG Prescaler.
* @param WWDG_Prescaler: specifies the WWDG Prescaler.
* This parameter can be one of the following values:
* @arg WWDG_Prescaler_1: WWDG counter clock = (PCLK1/4096)/1
* @arg WWDG_Prescaler_2: WWDG counter clock = (PCLK1/4096)/2
* @arg WWDG_Prescaler_4: WWDG counter clock = (PCLK1/4096)/4
* @arg WWDG_Prescaler_8: WWDG counter clock = (PCLK1/4096)/8
* @retval None
*/
void WWDG_SetPrescaler(uint32_t WWDG_Prescaler)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_WWDG_PRESCALER(WWDG_Prescaler));
/* Clear WDGTB[1:0] bits */
tmpreg = WWDG->CFR & CFR_WDGTB_MASK;
/* Set WDGTB[1:0] bits according to WWDG_Prescaler value */
tmpreg |= WWDG_Prescaler;
/* Store the new value */
WWDG->CFR = tmpreg;
}
(4)初始化中断结构体
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;//窗口中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器
(5)设置计数器初始值并使能WWDG
WWDG_Enable(0x7f); //使能窗口看门狗并初始化计数器值,看门狗控制器寄存器WDGA置1
WWDG_ClearFlag(); //清除窗口看门狗状态标志(这一句必须加上,否则进入不了中断)
//使能WWDG函数
void WWDG_Enable(uint8_t Counter)
{
/* Check the parameters */
assert_param(IS_WWDG_COUNTER(Counter));
WWDG->CR = WWDG_CR_WDGA | Counter;
}
//清除看门狗状态标志函数
void WWDG_ClearFlag(void)
{
WWDG->SR = (uint32_t)RESET;
}
(6)开启看门狗中断
//看门狗中断使能函数
void WWDG_EnableIT(void)
{
*(__IO uint32_t *) CFR_EWI_BB = (uint32_t)ENABLE;
}
(7)编写看门狗中断函数
/*******************************************************************************
* 函 数 名 : WWDG_IRQHandler
* 函数功能 : WWDG中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void WWDG_IRQHandler(void)
{
WWDG_SetCounter(0x7f); //重新赋值
WWDG_ClearFlag(); //清除窗口看门狗状态标志
}
3.2完整窗口看门狗初始化函数
/*******************************************************************************
* 函 数 名 : WWDG_Init
* 函数功能 : WWDG初始化
窗口值是:0x5f
定时器计数值是:0x7f
预分频值是:8
窗口看门狗进入中断的频率计算公式是:PCLK1/(4096*2^pre)
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void WWDG_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE); //开启窗口看门狗的时钟
WWDG_SetWindowValue(0x5f);//设置窗口值
WWDG_SetPrescaler(WWDG_Prescaler_8);//设置分频值
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;//窗口中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器
WWDG_Enable(0x7f); //使能窗口看门狗并初始化计数器值
WWDG_ClearFlag(); //清除窗口看门狗状态标志(这一句必须加上,否则进入不了中断)
WWDG_EnableIT(); //开启中断
}
/*******************************************************************************
* 函 数 名 : WWDG_IRQHandler
* 函数功能 : WWDG中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void WWDG_IRQHandler(void)
{
WWDG_SetCounter(0x7f); //重新赋值
WWDG_ClearFlag(); //清除窗口看门狗状态标志
}
讲解不到位的希望大家指出,有需要我讲解的部分,希望大家提出,我会出文档讲解。