32单片机——窗口看门狗

1、WWDG的简介

WWDG:Window watchdog,即窗口看门狗

窗口看门狗本质上是能产生系统复位信号和提前唤醒中断的递减计数器

WWDG产生复位信号的条件:

(1)当递减计数器值从0x40减到0x3F时复位(即T6位跳变到0)

(2)计数器的值大于W[6:0]值时喂狗会复位

(3)提前唤醒中断(EWI):当递减计数器等于0x40时可产生

喂狗:在窗口期(W[6:0]值~0x40)内重装载计数器的值,防止复位

作用:用于监测单片机程序运行时效是否精准,主要检测软件异常

应用:需要精准检测程序运行时间的场合

2、WWDG的工作原理

3、WWDG的框图

4、WWDG超出时间计算

:WWDG超出时间

:WWDG的时钟源频率,36MHZ

4096:WWDG固定的预分频系数

:wwDG_CFR寄存器设置的预分频系数值

T[5:0]:WWDG计数器低6位

5、WWDG的配置步骤

(1)WWDG工作参数初始化

HAL_WWDG_Init();
HAL_StatusTypeDef HAL_WWDG_Init(WWDG_HandleTypeDef *hwwdg);
{

WWDG_TypeDef *Instance; /* 寄存器基地址 */

WWDG_InitTypeDef Init; /* WWDG必需参数 */

#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1)

void (* EwiCallback)(struct __WWDG_HandleTypeDef *hwwdg);

void (* MspInitCallback)(struct __WWDG_HandleTypeDef *hwwdg);

#endif /* USE_HAL_WWDG_REGISTER_CALLBACKS */

} WWDG_HandleTypeDef;
typedef struct

{

uint32_t Prescaler; /* 预分频系数 */

uint32_t Window; /* 0x3f<窗口值≤W[6:0] */

uint32_t Counter; /* 计数器值:0x40~0x7F */

uint32_t EWIMode ; /* 提前唤醒中断使能 */

} WWDG_InitTypeDef;

Prescaler的参数如下所示:

#define WWDG_PRESCALER_1 0x00000000u

/* WWDG计数器时钟=(PCLK1/4096)/1 */

#define WWDG_PRESCALER_2 WWDG_CFR_WDGTB_0

/*!< WWDG计数器时钟=(PCLK1/4096)/2 */

#define WWDG_PRESCALER_4 WWDG_CFR_WDGTB_1

/*!< WWDG计数器时钟=(PCLK1/4096)/4 */

#define WWDG_PRESCALER_8 (WWDG_CFR_WDGTB_1 | WWDG_CFR_WDGTB_0) /* WWDG计数器时钟=(PCLK1/4096)/8 */

EWIMode的参数如下所示:

#define WWDG_EWI_DISABLE 0x00000000u /* EWI禁用 */

#define WWDG_EWI_ENABLE WWDG_CFR_EWI /* EWI启用 */

(2)WWDG的Msp初始化

HAL_WWDG_MspInit();
__weak void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg);

(3)设置优先级,使能中断

HAL_NVIC_SetPriority();

在32单片机------外部中断_32中断-CSDN博客中解释过

(4)编写中断服务函数

WWDG_IRQHandler(); //设置在startup_stm32f103xe.s中

HAL_WWDG_IRQHandler(); //中断公共处理函数
void HAL_WWDG_IRQHandler(WWDG_HandleTypeDef *hwwdg)

{

/* Check if Early Wakeup Interrupt is enable */

if (__HAL_WWDG_GET_IT_SOURCE(hwwdg, WWDG_IT_EWI) != RESET)

{

/* Check if WWDG Early Wakeup Interrupt occurred */

if (__HAL_WWDG_GET_FLAG(hwwdg, WWDG_FLAG_EWIF) != RESET)

{

/* Clear the WWDG Early Wakeup flag */

__HAL_WWDG_CLEAR_FLAG(hwwdg, WWDG_FLAG_EWIF);

#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1)

/* Early Wakeup registered callback */

hwwdg->EwiCallback(hwwdg);

#else

/* Early Wakeup callback */

HAL_WWDG_EarlyWakeupCallback(hwwdg);

#endif /* USE_HAL_WWDG_REGISTER_CALLBACKS */

}

}

}

(5)重定义提前唤醒回调函数

HAL_WWDG_EarlyWakeupCallback();

(6)在窗口期内喂狗

HAL_WWDG_Refresh();
HAL_StatusTypeDef HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg)

{

/* Write to WWDG CR the WWDG Counter value to refresh with */

WRITE_REG(hwwdg->Instance->CR, (hwwdg->Init.Counter));

/* Return function status */

return HAL_OK;

}

6、例子

先点亮LED0延时300ms后,初始化窗口看门狗,进入死循环,关闭LED0。然后等待窗口看门狗中断的到来,在中断里面,喂狗,并执行LED1的翻转操作。我们将通过LED0来指示STM32F1是否被复位了,如果被复位了就会点亮300ms。LED1用来指示中断喂狗,每次中断喂狗翻转一次。

wwdg.h

#ifndef _WWDG_H

#define _WWDG_H

#include "./SYSTEM/sys/sys.h"

#include "./SYSTEM/delay/delay.h"

//wwdg初始化

/*

参数1:定时器初始值

参数2:窗口值

参数3:预分频系数

*/

void wwdg_init(uint8_t tr,uint8_t wr,uint8_t prer);

#endif

wwdg.c

#include "./BSP/WWDG/wwdg.h"
WWDG_HandleTypeDef wwdg_handle; //wwdg句柄

void wwdg_init(uint8_t tr,uint8_t wr,uint8_t prer){

//初始化wwdg的工作参数

wwdg_handle.Instance=WWDG; //寄存器基地址

wwdg_handle.Init.Counter=tr; //计数器值

wwdg_handle.Init.EWIMode=WWDG_EWI_ENABLE; //提前唤醒中断使能

wwdg_handle.Init.Prescaler=prer; //预分频系数

wwdg_handle.Init.Window=wr; //窗口值

HAL_WWDG_Init(&wwdg_handle);

}

//窗口看门狗的Msp回调:一般用来设置GPIO、NVIC、CLOCK

void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg){

__HAL_RCC_WWDG_CLK_ENABLE(); //使能时钟

HAL_NVIC_SetPriority(WWDG_IRQn,0,0); //设置优先级

HAL_NVIC_EnableIRQ(WWDG_IRQn); //使能提前唤醒中断

}

//窗口看门狗提前唤醒中断的服务函数

void WWDG_IRQHandler(void){

HAL_WWDG_IRQHandler(&wwdg_handle); //中断公共处理函数

}

//提前唤醒中断的回调函数

//在此函数内写中断逻辑代码

void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg){

if(hwwdg->Instance==WWDG){

//喂狗

HAL_WWDG_Refresh(hwwdg);

//HAL_WWDG_Refresh(&wwdg_handle); //效果同上

}

}

main.c

#include "./SYSTEM/delay/delay.h"

#include "./SYSTEM/usart/usart.h"

#include "./BSP/LED/led.h"

#include "./BSP/BEEP/beep.h"

#include "./BSP/KEY/key.h"

#include "./BSP/WWDG/wwdg.h"

int main(void){

HAL_Init();

sys_stm32_clock_init(RCC_PLL_MUL9); //设置系统时钟

delay_init(72);

led_init();

beep_init();

key_init();

HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET);

delay_ms(100);

wwdg_init(0x7f,0x5f,WWDG_PRESCALER_8); //初始化wwdg

while (1){

HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);

}

}

相关推荐
天天爱吃肉82183 分钟前
新能源汽车热管理核心技术解析:冬季续航提升40%的行业方案
android·python·嵌入式硬件·汽车
章鱼哥嵌入式开发8 分钟前
# STM32F103 SD卡读写程序
stm32·单片机
广药门徒1 小时前
定时器时钟来源可以从输入捕获引脚输入
单片机·嵌入式硬件
爱睡觉的王宇昊5 小时前
二、【ESP32开发全栈指南:ESP32 GPIO深度使用】
单片机·嵌入式硬件
三三十二11 小时前
STM32实战:数字音频播放器开发指南
stm32·单片机·嵌入式硬件
想搞嵌入式的小白13 小时前
STM32外设问题总结
单片机·嵌入式硬件
木子单片机15 小时前
基于STM32语音识别柔光台灯
stm32·单片机·嵌入式硬件·proteus·语音识别·keil
广药门徒15 小时前
澄清 STM32 NVIC 中断优先级
单片机·嵌入式硬件
小灰灰搞电子16 小时前
单片机0-10V电压输出电路分享
单片机·嵌入式硬件