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);

}

}

相关推荐
Ronin-Lotus10 小时前
嵌入式硬件篇---ESP32驱动异常
嵌入式硬件·esp32
Cyrus_柯10 小时前
单片机(STM32-ADC模数转换器)
stm32·单片机·嵌入式硬件·adc
南山十一少10 小时前
STM32CubeMX + HAL库:基于DHT11温湿度监测实现
stm32·单片机·嵌入式硬件
Hallin_Me12 小时前
单片机的第一个程序—LED灯的控制
单片机·嵌入式硬件
乌恩大侠14 小时前
卫星物联网:使用兼容 Arduino 的全新 Iridium Certus 9704 开发套件深入探索
单片机·嵌入式硬件·物联网
lixzest15 小时前
Stm32中USB 对时钟的要求
stm32·单片机·嵌入式硬件
螺丝钉的扭矩一瞬间产生高能蛋白15 小时前
MCU+RTOS调试
c语言·stm32·单片机·嵌入式硬件·嵌入式
范纹杉想快点毕业15 小时前
Zynq SOC FPGA嵌入式裸机设计和开发教程自学笔记:硬件编程原理、基于SDK库函数编程、软件固化
网络·笔记·stm32·单片机·嵌入式硬件·tcp/ip·fpga开发
安庆平.Я17 小时前
STM32——寄存器映射
c语言·stm32·单片机·嵌入式硬件·电脑
佳航张18 小时前
单片机启动流程和启动文件详解
单片机·嵌入式硬件