STM32 HAL库开发-IWDG(独立看门狗)
一、IWDG简介
1、IWDG全程为Independent watchdog,即独立看门狗。
2、IWDG的本质为能产生系统复位信号的计数器。
3、IWDG的特性
4、喂狗
在计数器计数到0之前,重装载计数器的值,防止复位。有一个重装在寄存器。
二、IWDG作用
1、异常:外界电磁干扰或者自身系统(硬件或软件)异常造成程序跑飞,如:陷入某个不正常的死循环,打断正常的程序运行。就是常说的死机了。
2、作用:主要用于检测外界电磁干扰,或硬件异常导致的程序跑飞问题。主要是解决硬件错误,进行复位。软件错误的由WWDG(窗口看门狗)解决。
3、应用:在一些需要高稳定性的产品中,并且对时间精度要求较低的场合。由于RC振荡器精度不高。
总结:IWDG是异常处理的最后手段,不可依赖,应该在设计的时候尽量避免一场发生。
三、IWDG工作原理
其中,Src CLK就是独立时钟源RC振荡器,经过预分频器PSC,得到IWDG的工作时钟IWDG CLK,每来一个时钟信号,计数器CNT的值就会减一,当CNT的值为0的时候,就会产生复位。为了不复位,就需要在CNT减到0之前喂狗,将重装载寄存器RELOAD的值写入CNT中。
LSI:低速的内部振荡器, 启用IWDG后,LSI时钟会自动开启。就是使能了IWDG后,LSI时钟自动开启。LSI时钟频率并不精确,(F1用40kHz,F4/F7/H7用32kHz进行计算即可),由于是RC振荡器,所以不精确。
12位递减计数器:最大值为2的12次方,即4096,可以设置比4096小的值。
四、IWDG寄存器
1、键寄存器(IWDG_KR)
通过写入不同的键值,实现不同功能。写入0XAAAA就是喂狗,写入0X5555表示允许访问IWDG_PR和IWDG_RLR寄存器,写入0XCCCC,启动看门狗工作。硬件看门狗不受0XCCCC指令控制。硬件看门狗和软件看门狗在闪存编程手册里边设置,硬件看门狗在复位后自动启动,不能关闭,必须在规定时间内喂狗,不然自动复位。选择软件看门狗就是写入0XCCCC指令才能启动看门狗。而这个控制软件还是硬件看门狗的寄存器在USER里边,程序里在stm32f103xe.h里的寄存器基地址的OB结构体里边。
2、预分频器寄存器(IWDG_PR)
低三位有效,只能设置8种分频,具体看参考手册。
3、重装载寄存器(IWDG_RLR)
低12位有效,在这个寄存器里设置重装载值,然后在键寄存器(IWDG_KR)里写入0XAAAA就会将重装载寄存器(IWDG_RLR)里的值写入到计数器里边。
4、状态寄存器(IWDG_SR)
只有两个有效位,一个是PVU位,当预分频值更新完成后,这位会置1,另一个是RVU位,当重装载值写入到计数器里边,这个位会被置1。
五、IWDG寄存器配置操作步骤
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)。
六、溢出时间计算
这个很简单,自己手推一下就出来了。
下图给出了配置表,其中最短时间就是时钟线来一个信号,计数器就溢出了。最大值就是0XFFF,也就是4096个信号计数器溢出。
七、IWDG配置步骤 (HAL库)
1、HAL_IWDG_Init()函数,取消PR/RLR寄存器写保护,设置IWDG预分频系数和重装载值,启动IWDG。
2、HAL_IWDG Refresh()函数,及时喂狗,即写入0xAAAA到IWDG_KR。
八、程序
iwdg.h 头文件程序
#ifndef __IWDG_H
#define __IWDG_H
#include "stm32f1xx.h"
void IWDG_Init(uint8_t prer,uint16_t rlr);
void IWDG_feed(void);
#endif
iwdg.c 源程序文件
#include "./BSP/iwdg/iwdg.h"
IWDG_HandleTypeDef hiwdg;
void IWDG_Init(uint8_t prer,uint16_t rlr)
{
hiwdg.Instance = IWDG;
//预分频系数
hiwdg.Init.Prescaler = prer;
//重装载值
hiwdg.Init.Reload = rlr;
HAL_IWDG_Init(&hiwdg);
}
//喂狗函数 就是调用了HAL_IWDG_Refresh(&hiwdg);
void IWDG_feed(void)
{
HAL_IWDG_Refresh(&hiwdg);
}
main.c 主函数程序
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/iwdg/iwdg.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
USART_Init(115200);
UART_Transmit((uint8_t *)"您还没喂狗,请计时喂狗!!!\r\n",sizeof("您还没喂狗,请计时喂狗!!!\r\n"));
//设置IWDG溢出时间为1S,这里先根据使用手册选出来分频系数,然后根据公式计算重装载值
IWDG_Init(IWDG_PRESCALER_32,1250);
while(1)
{
delay_ms(1055);
IWDG_feed();//喂狗
UART_Transmit((uint8_t *)"已经喂狗\r\n",sizeof("已经喂狗\r\n"));
}
}
现象: 设置的溢出时间是1S,在while(1)循环里边控制delay_ms()函数,超过1S,就会复位,一直打印”您还没喂狗“,小于1S,就会喂狗,打印”已经喂狗“。
作者:猿~~~