【7】STM32·HAL库·看门狗
目录
一、IWDG简介
二、IWDG工作原理
三、IWDG框图
四、IWDG寄存器
4.1、关键字寄存器(IWDG_KR)
4.2、预分频器寄存器(IWDG_PR)
4.3、重载寄存器(IWDG_RLR)
4.4、状态寄存器(IWDG_SR)
4.5、寄存器配置操作步骤
五、IWDG溢出时间计算
5.1、IWDG溢出时间计算公式(HAL库)
5.2、寄存器设置分频系数的方法
5.3、IWDG溢出时间计算公式(寄存器)
5.4、IWDG最短最长超时时间(F4/F7/H7)
六、IWDG配置步骤
6.1、使能并初始化IWDG
6.2、及时喂狗
七、编程实战:验证不及时喂狗,系统将复位重启
八、WWDG简介
九、WWDG工作原理
十、WWDG框图
十一、WWDG寄存器
11.1、控制寄存器(WWDG_CR)
11.2、配置寄存器(WWDG_CFR)
11.3、状态寄存器(WWDG_SR)
十二、WWDG超时时间计算
十三、WWDG配置步骤
13.1、使能并初始化WWDG
13.2、窗口期喂狗
十四、编程实战:验证窗口看门狗功能
十五、IWDG和WWDG的主要区别
一、IWDG简介
IWDG(Independent watchdog),即独立看门狗
本质:能产生系统复位信号的计数器
特性:递减的计数器,时钟由独立的 RC 振荡器提供(可在待机和停止模式下运行),看门狗被激活后,当递减计数器计数到 0x000 时产生复位
喂狗:在计数器计数到 0 之前,重装载计数器的值,防止复位
异常 | 外界电磁干扰或者自身系统(硬件或软件)异常,造成程序跑飞,如:陷入某个不正常的死循环,打断正常的程序运行 |
作用 | 主要用于检测外界电磁干扰,或硬件异常导致的程序跑飞问题 |
应用 | 在一些需要高稳定性的产品中,并且对时间精度要求较低的场合 |
独立看门狗是异常处理的最后手段,不可依赖,应在设计时尽量避免异常的发生!
二、IWDG工作原理
原理图
CPU 必须及时喂狗,否则系统复位重启!
三、IWDG框图
启用 IWDG 后,LSI 时钟会自动开启
LSI 时钟频率并不精确,F1 用 40kHz,F4/F7/H7 用 32kHz 进行计算即可
四、IWDG寄存器
4.1、关键字寄存器(IWDG_KR)
用于喂狗,解除PR和RLR寄存器写访问保护,以及启动看门狗工作
4.2、预分频器寄存器(IWDG_PR)
4.3、重载寄存器(IWDG_RLR)
用于存放重装载值,低12位有效,即最大值为4096
4.4、状态寄存器(IWDG_SR)
4.5、寄存器配置操作步骤
1、通过在键寄存器 (IWDG_KR) 中写入 0xCCCC 来使能 IWDG
2、通过在键寄存器 (IWDG_KR) 中写入 0x5555 来使能寄存器访问
3、通过将预分频器寄存器 (IWDG_PR) 编程为 0~7 中的数值来配置预分频器
4、对重载寄存器 (IWDG_RLR) 进行写操作
5、等待寄存器更新 (IWDG_SR = 0x0000 0000)
6、刷新计数器值为 IWDG_RLR 的值 (IWDG_KR = 0xAAAA)
五、IWDG溢出时间计算
5.1、IWDG溢出时间计算公式(HAL库)
5.2、寄存器设置分频系数的方法
5.3、IWDG溢出时间计算公式(寄存器)
5.4、IWDG最短最长超时时间(F4/F7/H7)
六、IWDG配置步骤
6.1、使能并初始化IWDG
取消 PR/RLR 寄存器写保护,设置 IWDG 预分频系数和重装载值,启动 IWDG
HAL库驱动函数:HAL_IWDG_Init()
/** * @brief Initialize the IWDG according to the specified parameters in the * IWDG_InitTypeDef and start watchdog. Before exiting function, * watchdog is refreshed in order to have correct time base. * @param hiwdg pointer to a IWDG_HandleTypeDef structure that contains * the configuration information for the specified IWDG module. * @retval HAL status */ HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg);
关键结构体
/** * @brief IWDG Init structure definition */ typedef struct { uint32_t Prescaler; /*!6.2、及时喂狗
把重装载寄存器的值重载到计数器中,写入 0xAAAA 到 IWDG_KR,喂狗
HAL库驱动函数:HAL_IWDG_Refresh()
/** * @brief Refresh the IWDG. * @param hiwdg pointer to a IWDG_HandleTypeDef structure that contains * the configuration information for the specified IWDG module. * @retval HAL status */ HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg);七、编程实战:验证不及时喂狗,系统将复位重启
验证思路:按下 WKUP 时可喂狗,当超过 1s 没喂狗时系统将复位重启,LED0 反复初始化点亮,正常喂狗时 LED0 常亮
main.c
#include "./SYSTEM/sys/sys.h" #include "./SYSTEM/usart/usart.h" #include "./SYSTEM/delay/delay.h" #include "./BSP/LED/led.h" #include "./BSP/KEY/key.h" #include "./BSP/WDG/wdg.h" int main(void) { HAL_Init(); /* 初始化HAL库 */ sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */ delay_init(168); /* 延时初始化 */ usart_init(115200); /* 串口初始化为115200 */ led_init(); /* 初始化LED */ key_init(); /* 初始化按键 */ delay_ms(100); /* 延时100ms再初始化看门狗,LED0的变化"可见" */ iwdg_init(IWDG_PRESCALER_64, 500); /* 预分频数为64,重载值为500,溢出时间约为1s */ LED0(0); /* 点亮LED0(红灯) */ while (1) { if (key_scan(1) == WKUP_PRES) /* 如果WK_UP按下,则喂狗,支持连按 */ { iwdg_feed(); /* 喂狗 */ } delay_ms(10); } }wdg.c
#include "./BSP/WDG/wdg.h" IWDG_HandleTypeDef iwdg_handler; /*独立看门狗句柄 */ /** * @brief 初始化独立看门狗 * @param prer: IWDG_PRESCALER_4~IWDG_PRESCALER_256,对应4~256分频 * @arg 分频因子 = 4 * 2^prer. 但最大值只能是256! * @param rlr: 自动重装载值,0~0XFFF. * @note 时间计算(大概):Tout=((4 * 2^prer) * rlr) / 32 (ms). * @retval 无 */ void iwdg_init(uint32_t prer, uint16_t rlr) { iwdg_handler.Instance = IWDG; iwdg_handler.Init.Prescaler = prer; /* 设置IWDG分频系数 */ iwdg_handler.Init.Reload = rlr; /* 从加载寄存器 IWDG->RLR 重装载值 */ HAL_IWDG_Init(&iwdg_handler); /* 初始化IWDG并使能 */ } /* 喂独立看门狗 */ void iwdg_feed(void) { HAL_IWDG_Refresh(&iwdg_handler); /* 喂狗 */ }wdg.h
#ifndef __WDG_H #define __WDG_H #include "./SYSTEM/sys/sys.h" void iwdg_init(uint32_t prer, uint16_t rlr); /* 初始化IWDG,并使能IWDG */ void iwdg_feed(void); /* 喂狗 */ #endif八、WWDG简介
WWDG(Window watchdog),即窗口看门狗
本质:能产生系统复位信号和提前唤醒中断的计数器
特性:递减的计数器,当递减计数器值从 0x40 减到 0x3F 时复位(即 T6 位跳变到 0),计数器的值大于 W[6:0] 值时喂狗会复位,提前唤醒中断 (EWI):当递减计数器等于 0x40 时可产生
喂狗:在窗口期内重装载计数器的值,防止复位
作用 | 用于监测单片机程序运行时效是否精准,主要检测软件异常 |
应用 | 需要精准检测程序运行时间的场合 |
九、WWDG工作原理
注意:W[6:0] 必须大于窗口下限值 0x3F,否则无窗口期
十、WWDG框图
时钟源
PCLK1 | |
F103 | 36MHz |
F407 | 42MHz |
F429 | 45MHz |
F767 | 54MHz |
H743 | 100MHz |
十一、WWDG寄存器
11.1、控制寄存器(WWDG_CR)
用于使能窗口看门狗工作,以及重装载计数器值(即喂狗)
11.2、配置寄存器(WWDG_CFR)
用于使能窗口看门狗提前唤醒中断,设置预分频系数,设置窗口上限值
11.3、状态寄存器(WWDG_SR)
用于判断是否发生了 WWDG 提前唤醒中断
十二、WWDG超时时间计算
WWDG 超时时间计算公式
WWDG 最短最长超时时间(F4/F7/H7)
十三、WWDG配置步骤
13.1、使能并初始化WWDG
使能WWDG,设置预分频系数和窗口值等
HAL库驱动函数:HAL_WWDG_Init()
/** * @brief Initialize the WWDG according to the specified. * parameters in the WWDG_InitTypeDef of associated handle. * @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains * the configuration information for the specified WWDG module. * @retval HAL status */ HAL_StatusTypeDef HAL_WWDG_Init(WWDG_HandleTypeDef *hwwdg);
关键结构体
/** * @brief WWDG Init structure definition */ typedef struct { uint32_t Prescaler; /*!13.2、窗口期喂狗
重装载计数器,即喂狗
HAL库驱动函数:HAL_WWDG_Refresh()
/** * @brief Refresh the WWDG. * @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains * the configuration information for the specified WWDG module. * @retval HAL status */ HAL_StatusTypeDef HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg);十四、编程实战:验证窗口看门狗功能
验证思路:LED0 熄灭 LED1 闪烁说明正常喂狗,程序正常执行;LED1 熄灭 LED0 闪烁说明没有正常喂狗,程序反复执行复位
main.c
#include "./SYSTEM/sys/sys.h" #include "./SYSTEM/usart/usart.h" #include "./SYSTEM/delay/delay.h" #include "./BSP/LED/led.h" #include "./BSP/KEY/key.h" #include "./BSP/WDG/wdg.h" int main(void) { HAL_Init(); /* 初始化HAL库 */ sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */ delay_init(168); /* 延时初始化 */ usart_init(115200); /* 串口初始化为115200 */ led_init(); /* 初始化LED */ LED0(0); /* 点亮LED0(红灯) */ delay_ms(300); /* 延时100ms再初始化看门狗,LED0的变化"可见" */ wwdg_init(0X7F, 0X5F, WWDG_PRESCALER_8); /* 计数器值为7f,窗口寄存器为5f,分频数为8 */ while (1) { LED0(1); /* 关闭LED0(红灯) */ } }wdg.c
#include "./BSP/WDG/wdg.h" WWDG_HandleTypeDef wwdg_handler; /* 窗口看门狗句柄 */ /** * @brief 初始化窗口看门狗 * @param tr: T[6:0],计数器值 * @param tw: W[6:0],窗口值 * @note fprer:分频系数(WDGTB),范围:WWDG_PRESCALER_1~WWDG_PRESCALER_8,表示2^WDGTB分频 * Fwwdg=PCLK1/(4096*2^fprer). 一般PCLK1=42Mhz * @retval 无 */ void wwdg_init(uint8_t tr, uint8_t wr, uint32_t fprer) { wwdg_handler.Instance = WWDG; wwdg_handler.Init.Prescaler = fprer; /* 设置分频系数 */ wwdg_handler.Init.Window = wr; /* 设置窗口值 */ wwdg_handler.Init.Counter = tr; /* 设置计数器值 */ wwdg_handler.Init.EWIMode = WWDG_EWI_ENABLE; /* 使能窗口看门狗提前唤醒中断 */ HAL_WWDG_Init(&wwdg_handler); /* 初始化WWDG */ } /* WWDG底层驱动,时钟配置,中断配置 */ void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg) { __HAL_RCC_WWDG_CLK_ENABLE(); /* 使能窗口看门狗时钟 */ HAL_NVIC_SetPriority(WWDG_IRQn, 2, 3); /* 抢占优先级2,子优先级为3 */ HAL_NVIC_EnableIRQ(WWDG_IRQn); /* 使能窗口看门狗中断 */ } /* 窗口看门狗中断服务程序 */ void WWDG_IRQHandler(void) { HAL_WWDG_IRQHandler(&wwdg_handler); /* 调用WWDG共用中断处理函数 */ } void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg) { HAL_WWDG_Refresh(&wwdg_handler); /* 更新窗口看门狗值 */ LED1_TOGGLE(); /* 绿灯闪烁 */ }wdg.h
#ifndef __WDG_H #define __WDG_H #include "./SYSTEM/sys/sys.h" #include "./SYSTEM/delay/delay.h" #include "./BSP/LED/led.h" void wwdg_init(uint8_t tr, uint8_t wr, uint32_t fprer); /*窗口看门狗初始化*/ #endif十五、IWDG和WWDG的主要区别