• STM32(八):独立看门狗 (标准库函数)


    前言

    上一篇文章介绍了STM32单片机中的USART串口通信,这篇文章我们来介绍一下如何用STM32单片机中的独立看门狗来实现检测按键点灯的程序。

    一、实验原理

    单片机系统会由于受到外界的干扰,而造成程序执行紊乱,系统无法正常运行。为了防止这种情况的发生,产生了一种用于检测程序运行状态的电路或芯片,俗称看门狗(Watchdog)。

    1.看门狗的介绍

    看门狗(Watchdog)是一种硬件定时器,用于监测程序执行是否正常,并在系统出现故障或死锁时重启系统。看门狗可以分为独立与单片机外部的看门狗芯片和单片机内集成的看门狗外设模块两种,提供了更高的安全性、时间的精确性和使用的灵活性。而STM32F10x内置两个看门狗:IWDG(独立看门狗)WWDG(窗口看门狗)

    • IWDG(独立看门狗)

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

    • WWDG(窗口看门狗)

            由从APB1时钟分频后得到的时钟驱动,通过可配置的时间窗口来检测应用程序非正常的过迟或过早的操作。

    看门狗有一个输入信号,也称“喂狗”;有一个输出信号给MCU的复位端。系统运行后启动看门狗计数器,看门狗开始计数,当计数满后(一定时间)未收到清零信号(喂狗),看门狗计数器会溢出,引起看门狗中断,造成系统复位。

    而我们主要介绍一下IWDG(独立看门狗)。

    2.IWDG(独立看门狗)

    独立看门狗(Independent watchdog,IWDG)的时钟系统是由一个12位递减计数器和一个8位的预分频器构成的使用独立40KHZ内部低速LSI RC振荡器提供,可在停止和待机模式下工作。

    要想搞清楚IWDG的原理,那么首先还是先要学会看图,原理图如图所示:

    工作原理:

    • 在键寄存器(IWDG_KR)中写入0xCCCC,开始启用独立看门狗;
    • 此时计数器开始从其复位值0xFFF递减计数。当计数器计数到末尾0x000时,会产生一个复位信号(IWDG_RESET)。
    • 无论何时,只要在键寄存器IWDG_KR中写入0xAAAA(喂狗), IWDG_RLR中的值就会被重新加载到计数器,从而避免产生看门狗复位 。
    • IWDG_PR和IWDG_RLR寄存器具有写保护功能。要修改这两个寄存器的值,必须先向IWDG_KR寄存器中写入0x5555
    值得一提的是,看门狗功能处于VDD供电区,即在停机和待机模式时仍能正常工作。

    3.IWDG的寄存器

    STM32单片机的IWDG相关的寄存器有:键寄存器IWDG_KR、重装载寄存器IWDG_RLR、预分频寄存器IWDG_PR和状态寄存器IWDG_SR。下面将对其进行简单的说明:

    1.键寄存器IWDG_KR

    一个控制寄存器,主要有三种控制方式,由位15:0决定。

     2.重装载寄存器IWDG_RLR

    一个12位的寄存器,用于存放重装载值,低12位有效,即最大值为4096,这个值的大小决定着独立看门狗的溢出时间。   

    计算溢出的时间公式: Tout  = (PSC * RLR)/ LSI
    其中,PSC是分频系数,RLR计数器重装载值,LSI一般是40KHz。

     3.预分频寄存器IWDG_PR

    允许选择一个预分频因子,该因子决定了从低速内部时钟(LSI)到看门狗计时器的时钟频率。预分频值通过对LSI时钟频率进行分频来降低,从而增长看门狗计时器的计数周期。

    预分频的算法公式是:PSC = 4 * 2 PRER

    其中PRER就是IWDG_PR的值。

     4.状态寄存器IWDG_SR

    提供了有关看门狗重载操作和预分频值更新的实时信息,通过监测PVU和RVU位的状态,软件可以了解看门狗计时器的配置是否已经完成,从而确保看门狗定时器以预期的方式运行。

    二、实验步骤

    1.引脚初始化

    首先是使能预分频寄存器PR和重装载寄存器RLR

    IWDG_WriteAccessCmd( IWDG_WriteAccess_Enable );

    接下来是设置预分频器值和设置重装载寄存器值,并把重装载寄存器的值放到计数器中,具体设置的方法可以看下图

    1. /* 设置预分频器值 */
    2. IWDG_SetPrescaler( prv );
    3. /* 设置重装载寄存器值 */
    4. IWDG_SetReload( rlv );
    5. /* 把重装载寄存器的值放到计数器中 */
    6. IWDG_ReloadCounter();

    其中

    • prv:看门狗时钟预分频值(IWDG_ PR值);
    • rlv:看门狗的重装载值(IWDG_ RLR的值) ; 
    • 溢出时间的计算公式:Tout=((4x2^prv ) * rlv ) /40 

    以下为prv所能取到的值

     最后是并使能 IWDG

    1. /* 使能 IWDG */
    2. IWDG_Enable(); 

    2.喂狗函数

    把重装载寄存器的值放到计数器中,喂狗,防止IWDG复位,当计数器的值减到0的时候会产生系统复位。

    1. void IWDG_Feed(void)
    2. {
    3. IWDG_ReloadCounter();
    4. }

    3.按键检测

    key.c文件中加入KEY_lwdg(), IWDG_Feed()是喂狗,如果不喂狗,系统则会复位,LD1则会亮一次,如果在1s时间内准时喂狗的话,则LED1,LED2,LED3会常灭。

    ps:这边记得需要将bsp_iwdg.h也加入key.h文件中

    1. void KEY_lwdg(void)
    2. {
    3. /* 读取按键状态 */
    4. int key1State = KEYx_Choice(1);
    5. /* 短按按键1 */
    6. if (key1State == 1)
    7. {
    8. IWDG_Feed();
    9. }
    10. }

    三、实操代码

    程序分为3个文件:bsp_iwdg.c、bsp_iwdg.h、main.c

    1.bsp_iwdg.c 

    1. /* 包含头文件 ----------------------------------------------------------------*/
    2. #include "bsp/wdg/bsp_iwdg.h"
    3. void IWDG_Config(uint8_t prv ,uint16_t rlv)
    4. {
    5. /* 使能 预分频寄存器PR和重装载寄存器RLR可写 */
    6. IWDG_WriteAccessCmd( IWDG_WriteAccess_Enable );
    7. /* 设置预分频器值 */
    8. IWDG_SetPrescaler( prv );
    9. /* 设置重装载寄存器值 */
    10. IWDG_SetReload( rlv );
    11. /* 把重装载寄存器的值放到计数器中 */
    12. IWDG_ReloadCounter();
    13. /* 使能 IWDG */
    14. IWDG_Enable();
    15. }
    16. /**
    17. * 函数功能: 喂狗
    18. */
    19. void IWDG_Feed(void)
    20. {
    21. /* 把重装载寄存器的值放到计数器中,喂狗,防止IWDG复位
    22. 当计数器的值减到0的时候会产生系统复位 */
    23. IWDG_ReloadCounter();
    24. }

    2.bsp_iwdg.h

    1. #ifndef __BSP_IWDG_H__
    2. #define __BSP_IWDG_H__
    3. /* 包含头文件 ----------------------------------------------------------------*/
    4. #include
    5. /* 类型定义 ------------------------------------------------------------------*/
    6. /* 宏定义 --------------------------------------------------------------------*/
    7. /* 扩展变量 ------------------------------------------------------------------*/
    8. /* 函数声明 ------------------------------------------------------------------*/
    9. void IWDG_Feed(void);
    10. void IWDG_Config(uint8_t prv ,uint16_t rlv);
    11. #endif /* __BSP_IWDG_H__ */

    3.main.c

    1. /* 包含头文件 ----------------------------------------------------------------*/
    2. #include "stm32f10x.h"
    3. #include "bsp/led/bsp_led.h"
    4. #include "bsp/key/bsp_key.h"
    5. #include "bsp/delay/delay.h"
    6. #include "bsp/systick/bsp_SysTick.h"
    7. #include "bsp/GeneralTIM/bsp_GeneralTIM.h"
    8. #include "bsp/wdg/bsp_iwdg.h"
    9. /* 函数体 --------------------------------------------------------------------*/
    10. //static uint16_t timecount;
    11. __IO uint16_t timer_count=0;
    12. /**
    13. * 函数功能: 主函数.
    14. * 输入参数: 无
    15. * 返 回 值: 无
    16. * 说 明: 无
    17. */
    18. int main(void)
    19. {
    20. /* 初始化板载LED灯 */
    21. LED_GPIO_Init();
    22. /* 初始化按键 */
    23. KEY_GPIO_Init();
    24. Delay(1000);
    25. /* IWDG 1s 超时溢出 */
    26. IWDG_Config(IWDG_Prescaler_64 ,625);
    27. LED1_OFF;
    28. LED2_OFF;
    29. LED3_OFF;
    30. while (1)
    31. {
    32. KEY_lwdg();
    33. }
    34. }

    四、实验效果

    独立看门狗

    结束语

    本文以STM32VET6为例讲解了用STM32单片机中用IWDG(独立看门狗)来实现检测按键点灯的程序。希望对大家有所帮助!如果还有什么问题,欢迎评论区留言,谢谢!

  • 相关阅读:
    Unity中Shader光强与环境色
    热门开源项目ChatTTS: 国内语音技术突破,实现弯道超车
    Android studio:错误: 需要常量表达式
    【周末闲谈】谈谈数学转码这一年来的体会与反思
    66 内网安全-域横向批量at&schtasks&impacket
    Git Reset Origin – 如何将本地分支重置为远程跟踪分支
    产品工作流| 需求分析
    【创建微服务】创建微服务并使用人人开源代码生成器生成基本代码
    golang 函数式编程库samber/mo使用: Future
    使用React Buddy辅助React开发
  • 原文地址:https://blog.csdn.net/liutuoqi123/article/details/139280839