STM32 HAL库开发-IWDG(独立看门狗)

一、IWDG简介

1、IWDG全程为Independent watchdog,即独立看门狗。

2、IWDG的本质为能产生系统复位信号的计数器。

3、IWDG的特性

  • 递减的计数器,来一个时钟信号就减一。
  • 时钟由独立的RC振荡器提供(可在待机和停止模式下远看门狗被激活后,当递减计数器计数到0x000时产生复位)。
  • 时钟信号不是来自主时钟,STM32的主时钟一般来自于外部的HSE(晶振),如果外部的HSE坏了,一般会自动选择内部的HSI。而看门狗是独立的RC振荡器,时钟信号不是来自这两个。
  • 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,就会喂狗,打印”已经喂狗“。

     

    作者:猿~~~

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32 HAL库开发-IWDG(独立看门狗)

    发表回复