【STM32】看门狗

目录

  • 一、独立看门狗
    • [1. IWDG简介](#1. IWDG简介)
    • [2. IWDG工作原理及框图](#2. IWDG工作原理及框图)
    • [3. IWDG寄存器及函数介绍](#3. IWDG寄存器及函数介绍)
    • [4. IWDG溢出时间计算](#4. IWDG溢出时间计算)
    • [5. IWDG配置步骤](#5. IWDG配置步骤)
    • [6. 小实验:独立看门狗喂狗实验](#6. 小实验:独立看门狗喂狗实验)
  • 二、窗口看门狗
    • [1. WWDG简介](#1. WWDG简介)
    • [2. WWDG工作原理及框图](#2. WWDG工作原理及框图)
    • [3. WWDG寄存器及函数介绍](#3. WWDG寄存器及函数介绍)
    • [4. WWDG溢出时间计算](#4. WWDG溢出时间计算)
    • [5. WWDG配置步骤](#5. WWDG配置步骤)
    • [6. 小实验:窗口看门狗喂狗实验](#6. 小实验:窗口看门狗喂狗实验)

一、独立看门狗

1. IWDG简介

独立看门狗(Independent Watchdog,通常缩写为IWDG)主要作用是主要用于检测外界电磁干扰,或硬件异常导致的程序跑飞问题。

  • IWDG本质上是一个12位的递减计数器。当计数器的值从某个初始值开始递减,并一直减到0时,系统会产生一个复位信号(IWDG_RESET)。CPU在接收到这个复位信号后,会重新启动系统,以确保系统从可能的错误或死锁状态中恢复。
  • 在计数器的值减到0之前,如果程序通过特定的"喂狗"操作(即重置计数器的值)来刷新计数器,那么就不会产生复位信号,系统将继续正常运行。这种"喂狗"操作通常是由程序在正常运行时定期执行的,以确保IWDG不会因计数器超时而产生复位信号。
  • 它使用专用的低速时钟(LSI)作为时钟源,即使在主时钟发生故障时,IWDG仍然能够继续运行。IWDG可以在停止模式和待机模式下工作,确保在这些模式下系统仍然受到保护。

2. IWDG工作原理及框图

3. IWDG寄存器及函数介绍





4. IWDG溢出时间计算

c 复制代码
Tout:看门狗溢出时间
fIWDG:看门狗的时钟源频率
psc:看门狗预分频系数
rlr:看门狗重装载值

5. IWDG配置步骤

6. 小实验:独立看门狗喂狗实验

实验目的

配置 IWDG 溢出时间为 1 秒左右,并验证未及时喂狗时系统将被复位。

代码实现

main.c

c 复制代码
#include "sys.h"
#include "uart1.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "iwdg.h"

int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */      
    //LED初始化
    led_init();
    uart1_init(115200);
    iwdg_init(IWDG_PRESCALER_32,1250 - 1);
    printf("hello world\r\n");
    printf("狗儿肚子饿了,再不喂它的话就咬人了\r\n");
    
    if(__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) != RESET){
        printf("独立看门狗复位\r\n");
        __HAL_RCC_CLEAR_RESET_FLAGS();
    }else{
        printf("其他复位重启\r\n");
    }
    
    while(1)
    {
        delay_ms(500);
        iwdg_feed();
        printf("狗儿已经喂饱了,不会咬人了!\r\n");
    }
}

iwdg.c

c 复制代码
#include "iwdg.h"

IWDG_HandleTypeDef iwdg_handle = {0};

//独立看门口初始化
void iwdg_init(uint8_t psc, uint16_t rlr)
{
    iwdg_handle.Instance = IWDG;
    iwdg_handle.Init.Prescaler = psc;
    iwdg_handle.Init.Reload = rlr;
    HAL_IWDG_Init(&iwdg_handle);
}

//喂狗函数
void iwdg_feed(void)
{
    HAL_IWDG_Refresh(&iwdg_handle);
}

iwdg.h

c 复制代码
#ifndef __IWDG_H__
#define __IWDG_H__

#include "sys.h"

//独立看门口初始化
void iwdg_init(uint8_t psc, uint16_t rlr);
//喂狗函数
void iwdg_feed(void);

#endif

二、窗口看门狗

1. WWDG简介

窗口看门狗用于监测单片机程序运行时效是否精准,主要检测软件异常,一般用于需要精准检测程序运行时间的场合。

窗口看门狗的本质是一个能产生系统复位信号和提前唤醒中断的6位计数器。产生复位条件:

  • 当递减计数器值从 0x40 减到 0x3F 时复位(即T6位跳变到0)。
  • 计数器的值大于 W6:0 值时喂狗会复位。

产生中断条件:

  • 当递减计数器等于 0x40 时可产生提前唤醒中断 (EWI)。
  • 在窗口期内重装载计数器的值,防止复位,也就是所谓的喂狗。

2. WWDG工作原理及框图

3. WWDG寄存器及函数介绍

4. WWDG溢出时间计算

5. WWDG配置步骤

6. 小实验:窗口看门狗喂狗实验

实验目的

开启窗口看门狗,计数器值设置为 0X7F ,窗口值设置为 0X5F ,预分频系数为 8 。在 while 循环里喂狗,同时翻转 LED1 状态;在提前唤醒中断服务函数进行喂狗,同时翻转 LED2 状态。

代码实现

main.c

c 复制代码
#include "sys.h"
#include "uart1.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "wwdg.h"

int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */      
    //LED初始化
    led_init();
    //串口初始化
    uart1_init(115200);
    //窗口看门狗初始化
    wwdg_init(0x7F, 0x5F, WWDG_PRESCALER_8);
    
    if(__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST) != RESET){
        printf("独立看门狗复位\r\n");
        __HAL_RCC_CLEAR_RESET_FLAGS();
    }else{
        printf("其他复位重启\r\n");
    }
    
    while(1)
    {
        delay_ms(50);
        wwdg_feed();
        led2_toggle();
    }
}

wwdg.c

c 复制代码
#include "wwdg.h"
#include "led.h"

WWDG_HandleTypeDef wwdg_handle = {0};
//窗口看门狗初始化
void wwdg_init(uint8_t tr, uint8_t wr , uint32_t psc)
{
    wwdg_handle.Instance = WWDG;
    //设置定时器重装载值
    wwdg_handle.Init.Counter = tr;
    //设置窗口值
    wwdg_handle.Init.Window = wr;
    //设置分频系数
    wwdg_handle.Init.Prescaler = psc;
    //提前唤醒中断使能标志
    wwdg_handle.Init.EWIMode = WWDG_EWI_ENABLE;;
    HAL_WWDG_Init(&wwdg_handle);
}

//硬件相关初始化
void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg)
{
    //打开看门口时钟
    __HAL_RCC_WWDG_CLK_ENABLE();
    //设置中断优先级
    HAL_NVIC_SetPriority(WWDG_IRQn, 2, 2);
    //使能中断
    HAL_NVIC_EnableIRQ(WWDG_IRQn);
}

//中断服务函数
void WWDG_IRQHandler(void)
{
    //公共服务函数
    HAL_WWDG_IRQHandler(&wwdg_handle);
}

//喂狗函数
void wwdg_feed(void)
{
    HAL_WWDG_Refresh(&wwdg_handle);
}

//中断回调函数
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{
    //喂狗
    //wwdg_feed();
    led2_toggle();
}

wwdg.h

c 复制代码
#ifndef __WWDG_H__
#define __WWDG_H__

#include "sys.h"


//喂狗函数
void wwdg_feed(void);
void wwdg_init(uint8_t tr, uint8_t wr , uint32_t psc);

#endif
相关推荐
hongmai6668883 分钟前
ESP32-C61-WROOM-1-N8R2:Wi-Fi 6与RISC-V融合的中坚力量
人工智能·单片机·嵌入式硬件·物联网·智能家居·risc-v
华清远见IT开放实验室14 小时前
实验室建设案例 | 石家庄科技信息职业学院嵌入式实验室——从底层硬件到系统应用,一所应用型高校的嵌入式人才培养这样落地
linux·arm开发·stm32·嵌入式硬件·高校·实验室建设
AI的探索之旅16 小时前
AI辅助原理图评审:电源去耦、BOOT引脚、VCAP——19项逐一核查,遗漏?不存在的
人工智能·vscode·嵌入式硬件
茯苓gao16 小时前
嵌入式开发笔记:EtherCAT协议从硬件到软件完整配置指南——从零搭建一套EtherCAT通信系统
笔记·嵌入式硬件·学习
GeekArch16 小时前
第24讲:Vibe模式代码风格控制——适配Keil/STM32工程规范
人工智能·stm32·单片机·嵌入式硬件·mcu·决策树·ai编程
Freedom_my17 小时前
STM32项目3
stm32·单片机·嵌入式硬件
国科安芯18 小时前
星间光链路:AS32S601型抗辐射MCU在空间激光通信终端控制中的技术实现
服务器·网络·单片机·嵌入式硬件·物联网·安全·信息与通信
小李不困还能学20 小时前
基于 51 单片机的8 路抢答器设计教程
单片机·嵌入式硬件·mongodb·抢答器
CedarQR20 小时前
万字长文:从零在 RK3588 上部署 PaddleSpeech 中文 TTS 全流程(FastSpeech2 + HiFiGAN)
开发语言·c++·嵌入式硬件·ubuntu·json
萌动的小火苗20 小时前
嵌入式开发中的栈与队列:任务调度为什么依赖数据结构
数据结构·c++·单片机·嵌入式硬件