• STM32物联网项目-独立看门狗IWDG


    独立看门狗IWDG

    独立看门狗(IWDG)由专用的低速时钟(LSI)驱动,即使主时钟发生故障它也仍然有效。

    IWDG最适合应用于那些需要看门狗作为一个在主程序之外,能够完全独立工作,并且对时间精度要求较低的场合。

    IWDG主要性能

    自由运行的递减计数器

    时钟由独立的RC振荡器提供(可在停止和待机模式下工作)

    看门狗被激活后,则在计数器计数至0x000时产生复位

    IWDG功能描述

    在键寄存器(IWDG_KR)中写入0xCCCC,开始启用独立看门狗;此时计数器开始从其复位值 0xFFF递减计数。当计数器计数到末尾0x000时,会产生一个复位信号(IWDG_RESET)。 无论何时,只要在键寄存器IWDG_KR中写入0xAAAA, IWDG_RLR中的值就会被重新加载到 计数器,从而避免产生看门狗复位 。

    在这里插入图片描述

    IWDG超时时间计算

    在这里插入图片描述

    由于独立看门狗是由LSI内部低速时钟提供振荡源,频率是40KHz,会经过预分频系数得到一个较小的频率,然后对重装载寄存器IWDG_RLR设定计数值,就能设定独立看门狗超时时间

    例如:想要设定超时时间为2秒,则看上方表的最长时间,在32分频之后可以定时3秒多,但在16分频时定时才1.6秒左右,达不到2秒,所以选择32分频之后的预分频系数都满足要求,则

    看门狗频率:40KHz / 32 = 1250Hz,也就是振动源振动1250次就定时1秒,那要定时2秒,就振动1250 * 2 = 2500次,所以重装载寄存器IWDG_RLR的设定值就为2500,这样就能使独立看门狗超过2秒后产生系统复位

    CubeMX配置

    独立看门狗配置

    在这里插入图片描述

    在这里插入图片描述

    经过上面的计算,定时2秒,所以预分频系数为32,重装载值为2500,便完成了独立看门狗的初始化

    在这里插入图片描述

    程序

    iwdg.c

    独立看门狗的初始化函数比较简单,就是把CubeMX设置的预分频系数和重装载值赋给结构体变量

    /* Includes ------------------------------------------------------------------*/
    #include "iwdg.h"
    
    /* USER CODE BEGIN 0 */
    
    /* USER CODE END 0 */
    
    IWDG_HandleTypeDef hiwdg;
    
    /* IWDG init function */
    void MX_IWDG_Init(void)
    {
    
      hiwdg.Instance = IWDG;
      hiwdg.Init.Prescaler = IWDG_PRESCALER_32;
      hiwdg.Init.Reload = 2500;
      if (HAL_IWDG_Init(&hiwdg) != HAL_OK)
      {
        Error_Handler();
      }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    stm32f1xx_hal_iwdg.h

    HAL库的独立看门狗只有两个函数,一个是初始化函数,另一个是喂狗函数,在自己的程序中调用该喂狗函数,就能实现喂狗
    在这里插入图片描述

    点击喂狗函数的具体实现代码,就能看到函数底层是一个宏定义,实现功能是将IWDG_KEY_RELOAD写入键寄存器KR,这样IWDG_RLR寄存器中的值就会被重新加载到计数器,防止看门狗计数溢出复位

    /**
      * @brief  Reload IWDG counter with value defined in the reload register
      *         (write access to IWDG_PR and IWDG_RLR registers disabled).
      * @param  __HANDLE__  IWDG handle
      * @retval None
      */
    #define __HAL_IWDG_RELOAD_COUNTER(__HANDLE__)       WRITE_REG((__HANDLE__)->Instance->KR, IWDG_KEY_RELOAD)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    而IWDG_KEY_RELOAD的值也可查看到,是0xAAAA,与文章开头提到的独立看门狗功能描述一致

    #define IWDG_KEY_RELOAD                 0x0000AAAAu  /*!< IWDG Reload Counter Enable   */
    
    • 1
    MyIWDG.c

    看门狗喂狗标志初始化为TRUE,喂狗函数Feed直接调用HAL库函数的喂狗函数HAL_IWDG_Refresh即可

    /* Includes ------------------------------------------------------------------*/
    #include "MyApplication.h"
    
    /* Private define-------------------------------------------------------------*/
    
    /* Private variables----------------------------------------------------------*/
    static void Feed(void);
    /* Public variables-----------------------------------------------------------*/
    MyIWDG_t MyIWDG =
    {
        TRUE,
        Feed
    };
    /* Private function prototypes------------------------------------------------*/
    
    /*
    * @name   Feed
    * @brief  喂狗
    * @param  None
    * @retval None   
    */
    static void Feed()
    {
        //喂狗操作
        HAL_IWDG_Refresh(&hiwdg);
    }
    /********************************************************
      End Of File
    ********************************************************/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    System.c

    自己定义的系统运行函数中,就通过判断标志位来调用喂狗函数

    /*
    * @name   Run
    * @brief  系统运行
    * @param  None
    * @retval None   
    */
    static void Run()
    {
        /*省略获取SHT30温湿度并往串口打印部分代码*/
        
        //独立看门狗喂狗操作
        if(MyIWDG.IWDG_Feed_Flag == TRUE)
        {
            printf("喂狗,程序正在运行\r\n");
            MyIWDG.Feed();
        }
    
        //延时
        HAL_Delay(1000);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    CallBack.c

    按键触发外部中断,将喂狗标志位IWDG_Feed_Flag清零,则停止喂狗,系统将复位

    系统复位后,喂狗标志位IWDG_Feed_Flag又会被初始化为TRUE,所以在主函数中会执行喂狗操作,不会再造成系统复位

    /*
    * @name   HAL_GPIO_EXTI_Callback
    * @brief  外部中断回调函数
    * @param  GPIO_Pin:触发外部中断的引脚
    * @retval None   
    */
    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    {
      if(GPIO_Pin == KEY1_Pin)
      {
        MyIWDG.IWDG_Feed_Flag = FALSE;
        LED.LED_Fun(LED2,LED_ON);
        printf("停止喂狗,系统将复位!\r\n");
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    实验效果

    系统每隔一秒执行喂狗操作,程序正常运行,如果触摸按键1按下,则停止喂狗操作,稍后系统就会复位重启,会打印系统初始化信息,再通过喂狗让系统运行

    在这里插入图片描述

    在做低功耗产品时,不能使用独立看门狗,因为当系统处于待机或者停止状态时,不会进行喂狗,但独立看门狗依然会计数,就会让系统复位,无法保持低功耗模式

    窗口看门狗由内部的PCLK1提供时钟,当系统待机时,PCLK也会停止工作,所以窗口看门狗也会停止工作,可以用来做低功耗产品

  • 相关阅读:
    VFP技巧
    张一鸣:我遇到的优秀年轻人的5个特质
    开发两年,作为过来人的建议
    Linux性能优化-网络篇-DNS问题排查
    Arbitrum Stylus 的工作原理
    切分集合的奇技淫巧——stream
    一、根据系统架构定位系统性能瓶颈
    变电站监控视频中异常物检测技术的研究
    Java之JvisualVM简介
    springboot读取配置文件自定义参数和自定义配置文件参数
  • 原文地址:https://blog.csdn.net/weixin_46251230/article/details/126747389