窗口看门狗(WWDG)通常被用来监测由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。除非递减计数器的值在 T6 位 (WWDG->CR 的第六位)变成 0 前被刷新,看门狗电路在达到预置的时间周期时,会产生一个 MCU 复位。在递减计数器达到窗口配置寄存器(WWDG->CFR)数值之前,如果 7 位的递减计数器数值(在控制寄存器中)被刷新, 那么也将产生一个 MCU 复位。这表明递减计数器需要在一个有限的时间窗口中被刷新。
库函数中用中断的方式来喂狗的方法,窗口看门狗库函数相关源码和定义分布在文件stm32f10x_wwdg.c 文件和头文件 stm32f10x_wwdg.h 中。步骤如下:
1)使能 WWDG 时钟
WWDG使用的是 PCLK1 的时钟,需要先使能时钟。方法是:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); // WWDG 时钟使能
2)设置窗口值和分频数
设置窗口值的函数是:
void WWDG_SetWindowValue(uint8_t WindowValue);
这个函数就一个入口参数为窗口值,很容易理解。
设置分频数的函数是:
void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);
这个函数同样只有一个入口参数就是分频值。
3)开启 WWDG 中断并分组
开启 WWDG 中断的函数为:
WWDG_EnableIT(); //开启窗口看门狗中断
接下来是进行中断优先级配置,使用 NVIC_Init()函数即可。
4)设置计数器初始值并使能看门狗
这一步在库函数里面是通过一个函数实现的:
void WWDG_Enable(uint8_t Counter);
该函数既设置了计数器初始值,同时使能了窗口看门狗。
5)编写中断服务函数
在最后,还是要编写窗口看门狗的中断服务函数,通过该函数来喂狗,喂狗要快,否则当窗口看门狗计数器值减到 0X3F 的时候,就会引起软复位了。在中断服务函数里面也要将状态寄存器的 EWIF 位清空。
完成了以上 5 个步骤之后,我们就可以使用 STM32 的窗口看门狗了。
点击(此处)折叠或打开
- static u8 WWDG_CNT=0x7f; /*保存WWDG计数器的设置值,默认为最大. */
- /**
- * 初始化窗口看门狗
- * tr :T[6:0],计数器值
- * wr :W[6:0],窗口值
- * fprer:分频系数(WDGTB),仅最低2位有效
- * Fwwdg=PCLK1/(4096*2^fprer).
- */
- void WWDG_Init(u8 tr,u8 wr,u32 fprer)
- {
- // RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); /*WWDG时钟使能*/
- WWDG_SetPrescaler(fprer); /*设置IWDG预分频值*/
- WWDG_SetWindowValue(wr); /*设置窗口值*/
- WWDG_CNT=tr&WWDG_CNT; /* 初始化WWDG_CNT. */
- WWDG_Enable(WWDG_CNT); /*使能看门狗 , 设置 counter . */
- WWDG_ClearFlag(); /*清除提前唤醒中断标志位*/
- WWDG_NVIC_Init();/* 初始化窗口看门狗 NVIC */
- WWDG_EnableIT(); /* 开启窗口看门狗中断 */
- }
- /**
- * 窗口看门狗中断服务程序
- */
- void WWDG_NVIC_Init(void)
- {
- NVIC_InitTypeDef NVIC_InitStructure;
- NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn; /*WWDG中断*/
- /* 抢占2,子优先级3 */
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
- NVIC_Init(&NVIC_InitStructure);/* NVIC初始化*/
- }
- /**
- * 重设置WWDG计数器的值
- */
- void WWDG_Set_Counter(u8 cnt)
- {
- WWDG_Enable(cnt); /*使能看门狗 , 设置 counter . */
- }
- /**
- * 看门狗中断服务程序
- */
- void WWDG_IRQHandler(void)
- {
- WWDG_Set_Counter(WWDG_CNT);
- WWDG_ClearFlag(); /*清除提前唤醒中断标志位*/
- LED1 = ~LED1; /*LED状态翻转 */
- }
调用:WWDG_Init(0X7F,0X5F,WWDG_Prescaler_8);/* 计数器值为 7f,窗口寄存器为 5f,分频数为 8 */ |