stm32-看门狗(独立看门狗,窗口看门狗)

2023-10-26

基于野火教程的看门狗。
实验器材:stm32c8t6,LED灯,按键一个。

实验一:独立看门狗

1. 实验原理。

2.实验代码讲解。

3.实验现象。

实验二:窗口看门狗

1. 实验原理。

2.实验代码讲解。

3.实验现象。

在进入正题之前,我们先了解一下什么是看门狗。看门狗用于检测和解决由软件错误引起的故障,当计数器达到给定的超时值时,触发一个中断(仅适用于窗口看门狗)或系统复位。通俗的来讲,就是当程序跑飞,在规定的时间内系统复位,或产生中断。看门狗分为独立看门狗和窗口看门狗。独立看门狗用通俗一点的话来解释就是一个 12 位的递减计数器,当计数器的值从某个值一直减到 0 的时候,系统就会产生一个复位信号,即 IWDG_RESET。如果在计数没减到 0 之前,刷新了计数器的值的话,那么就不会产生复位信号,这个动作就是我们经常说的喂狗。 看门狗功能由 VDD 电压域供电,在停止模式和待机模式下仍能工作 。窗口看门狗跟独立看门狗一样,也是一个递减计数器不断的往下递减计数,当减到一个固定值 0X40时还不喂狗的话,产生复位,这个值叫窗口的下限, 是固定的值,不能改变。 这个是跟独立看门狗类似的地方,不同的地方是窗口看门狗的计数器的值在减到某一个数之前喂狗的话也会产生复位,这个值叫窗口的上限,上限值由用户独立设置。窗口看门狗计数器的值必须在上窗口和下窗口之间才可以喂狗,这就是窗口看门狗中窗口两个字的含义 。这是野火教程给的解释。
记下来我们进入正题:

实验一:独立看门狗

实验原理:

功能框图如下:
在这里插入图片描述①:独立看门狗的时钟由独立的RC振荡器提供LSI提供。主时钟发生故障时依然有效。另外就是LSI的频率在不同的温度和工作场合有漂移,因此看门狗适用于时间精确度低的场合。
②:递减寄存器的时钟由LSI经过寄存器IWDG_PR 分频得到。计数器时钟CK_CNT= 40/ 42^PRV,一个计数器时钟计数器就减一。
③:在这里插入图片描述
④:重装载寄存器里面装着要刷新到计数器的值。这个值决定着独立看门狗的溢出时间。超时时间 Tout = (4
2^prv) / 40 * rlv (s) , prv 是预分频器寄存器的值, rlv 是重装载寄存器的值。
⑤:键寄存器作为看门狗的控制寄存器有三种模式:在这里插入图片描述
要说明的是:写0XCCCC时是软件启动,一旦启动看门狗,只有复位才能关闭。
⑥:略。
看门狗的使用:一个程序运行的时间是50ms,我们设置的溢出时间是60ms,如果超过60ms还没有喂狗,就意味着程序跑飞了,系统就会自动复位。而后重新进行。

2.实验代码讲解:

.c中的代码如下

#include "bsp_iwdg.h"

// 超时时间计算:Tout = prv / 40 * rlv
// prv 可以取下列值:4,8,16,32,64,128,256,256
// IWDG_Prescaler_4: IWDG prescaler set to 4
// IWDG_Prescaler_8: IWDG prescaler set to 8
// IWDG_Prescaler_16: IWDG prescaler set to 16
// IWDG_Prescaler_32: IWDG prescaler set to 32
// IWDG_Prescaler_64: IWDG prescaler set to 64
// IWDG_Prescaler_128: IWDG prescaler set to 128
// IWDG_Prescaler_256: IWDG prescaler set to 256

// 形参 rlv用来设置重装载寄存器 IWDG_RLR的 值 , 取 值 范 围 为0~0XFFF 。

//初始化函数
void IWDG_Config(uint8_t prv, uint16_t rlv)
{
    // 使能 预分频器PR 和 重装载寄存器RLR 可写。
   IWDG_WriteAccessCmd( IWDG_WriteAccess_Enable );
   
   // 设置 预分频器值
   IWDG_SetPrescaler( prv );
   
   // 设置 重装载寄存器的值
   IWDG_SetReload( rlv );
  
   // 把重装载寄存器的值放到计数器中
   IWDG_ReloadCounter();
 
   // 使能 IWDG
   IWDG_Enable();
} 

// 喂狗函数
void IWDG_Feed(void)
{
    //把重装载寄存器的值放到计数器中,防止IWDG复位
   //当计数器的值减到零时,系统会复位
   IWDG_ReloadCounter();
 
}

.h中的代码如下:

#ifndef __BSP_IWDG_H
#define __BSP_IWDG_H

#include "stm32f10x.h"

void IWDG_Feed(void);
void IWDG_Config(uint8_t prv,uint16_t rlv);

#endif /* __BSP_IWDG_H */

main.c中的文件如下:

   //来到这里的时候,系统的时钟已经配置成72M。
   LED1_GPIO_Config();
   LED2_GPIO_Config();
  
   GPIO_SetBits(LED2_G_GPIO_PORT, LED2_G_GPIO_PIN);    //开始时,关闭绿灯
   SysTick_Delay_ms(1500);  // 延时 1.5 毫秒

     // 检查看门狗是否复位
   if( RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET )
  {
     // 看门狗复位时亮绿灯
     LED2_OFF;
     //  清除标志
     RCC_ClearFlag();
     //  如果一直不喂狗,会一直复位,加上前面的延时,会看到红灯闪烁
  }
  else 
  {
     // 不是独立看门狗复位时(可能为上电复位或手动复位),
     LED2_ON;
     SysTick_Delay_ms(500);
     LED2_OFF;
     SysTick_Delay_ms(500);
  }
  
  KEY1_GPIO_Config();
  IWDG_Config( IWDG_Prescaler_64 , 625 );   // prv = IWDG_Prescaler_64  ,rlv = 625  1秒的溢出时间

  while( 1 )
  { 
           // 以上代码为被监控的代码
     if(Key1_Scan(KEY1_GPIO_PORT ,KEY1_GPIO_PIN) == KEY1_ON  )
     {
        //喂狗操作,如果不喂狗,系统会复位,LED1则会灭一次,如果在一秒的时间内准时喂狗,绿灯会常亮
         IWDG_Feed();
        // 绿灯会常亮
        LED2_OFF;
     }          
  }   

3.实验现象:

我们设置的溢出时间是1秒,如果在1秒的时间内没有按下按键,那么程序就会在main.c中执行while(1)之前的程序,一直循环,我们就会看到绿灯闪烁的情况。如果在1秒内不停按下了按键,(阻止了递减计数器减到零,程序就不会复位。)那么绿灯就会一直亮着。(限于材料有限,if和else中的程序均由绿灯完成,请多包含!)

实验二:窗口看门:

开始之前,先来了解一下什么是窗口看门狗:

TR是窗口看门狗的计数器的值, WR 是窗口看门狗的上窗口值,均由用户独立设置。
功能框图:
在这里插入图片描述
①窗口看门狗的时钟:窗口看门狗的时钟PCLK1,PCLK1最大是36M。
②计数器的时钟:计数器的时钟由CK计时器经过预分频得到,分频系数由配置寄存器CFR-WDGTB配置,CK计时器的时钟=PCLK1/4096。计数器时钟CNT_CK=PCLK1/4096/(2*WDGTB),那么计数器递减一个数的时间T=1/CNT_CK。
③计数器:计数器手册上讲解的比我想说的更清楚:
在这里插入图片描述在这里插入图片描述

④窗口值:下限我们无法改变,能改变的只有上限。而这个值必须介于0X7F到0X40之间。我们要监控的程序段 A 运行的时间为 Ta,当执行完这段程序之
后就要进行喂狗,如果在窗口时间内没有喂狗的话,那程序就肯定是出问题了。一般计数器的值TR设置成最大 0X7F,窗口值为 WR,计数器减一个数的时间为 T,那么时间: (TRWR)*T 应该稍微大于 Ta 即可。
⑤计算看门狗超时时间:
在这里插入图片描述
窗口看门狗适用于外部不可抗干扰或者程序逻辑错误造成的程序跑飞情况。

2.实验代码讲解:

.c 文件代码如下:

#include "bsp_wwdg.h"

// 中断优先级初始化
static void WWDG_NVIC_Config(void)
{ 
    NVIC_InitTypeDef NVIC_InitStructure;

   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
   NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
}

// WWDG 配置函数
// tr 递减计数器的值,取值范围是0X7F-0X40
// wr 窗口值,取值范围为0X7F-0X40
// prv 预分频器值,有四种选择:
//                           WWDG_Prescaler_1
//                           WWDG_Prescaler_2
//                           WWDG_Prescaler_4
//                           WWDG_Prescaler_8

void WWDG_Config( uint8_t tr,uint8_t wr,uint32_t prv)
{
    // 开启WWDG时钟
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
   // 设置递减计数器的值
   WWDG_SetCounter(tr);
      // 设置预分频器的值
   WWDG_SetPrescaler(prv);      
   // 设置上窗口的值
   WWDG_SetWindowValue(wr);   
   // 设置计数器的值,使能WWDG
   WWDG_Enable(WWDG_CNT);  
   // 清除提前唤醒中断标志位
   WWDG_ClearFlag();    
   // 配置WWDG中断优先级
   WWDG_NVIC_Config();   
  // 开 WWDG中断
  WWDG_EnableIT();
}

void WWDG_Feed(void)
{
    // 喂狗,刷新递减计数器的值,设置成最大WDG_CNT = 0X7F
   WWDG_SetCounter(WWDG_CNT);
}

stm32f10x.it.c文件如下:
// WWDG 中断服务函数程序,如果发生了此中断,表示程序已经出现了故障,
// 这是一个死前中断,在此中断服务函数中应该干最重要的事,
// 这个时间具体有多长,看WDGTB的值决定:
// WDGTB:0 113us
// WDGTB:1 227us
// WDGTB:2 445us
// WDGTB:3 910us
void WWDG_IRQHandler(void)
{
//清除中断标志位
WWDG_ClearFlag();

// LED2亮,点亮LED只是示意性操作
// 真正使用的时候,应该是做最重要的事情
LED2_ON; // 这里以绿灯LED2常亮为最重要的事
}

// WWDG 中断服务函数程序,如果发生了此中断,表示程序已经出现了故障,
// 这是一个死前中断,在此中断服务函数中应该干最重要的事,
// 这个时间具体有多长,看WDGTB的值决定:
// WDGTB:0    113us
// WDGTB:1    227us
// WDGTB:2    445us
// WDGTB:3    910us
void WWDG_IRQHandler(void)
{
    //清除中断标志位
   WWDG_ClearFlag();
   
   // LED2亮,点亮LED只是示意性操作
   // 真正使用的时候,应该是做最重要的事情
    LED2_ON;   // 这里以绿灯LED2常亮为最重要的事
}

main.c文件如下:

uint8_t wwdg_tr, wwdg_wr;
    //来到这里的时候,系统的时钟已经配置成72M。
   LED1_GPIO_Config();
   LED2_GPIO_Config();
    // 开始之前先关闭LED1
   LED1_ON;   // 红灯关
    // 延时1秒 
   SysTick_Delay_ms(1000);  
    // 初始化 WWDG ,配置计数器的初始值,配置上窗口值,启动WWDG,使能提前唤醒中断
   WWDG_Config( 0X7F,0X5F,WWDG_Prescaler_8 ); 
   // 窗口值我们在初始化的时候设置为0X5F,这个值不会改变
   wwdg_wr = WWDG->CFR & 0X7F; 
   while( 1 )
  {     
    LED1_OFF;   
    wwdg_tr = WWDG->CR & 0X7F;
    if( wwdg_tr  < wwdg_wr )
    {
        // 喂狗,重新设置计数器的值为最大0X7F
       WWDG_Feed();
    }       
  }   

3.实验现象:

程序执行后LED1亮一段时间后会熄灭,之后就不会亮,而中断函数中的LED2不会灭(LED2指的是板子上的绿灯)。

刚入门,如果有错误,请及时指出,大佬勿喷!
欢迎交流学习,共同进步!

下方是我微信:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

stm32-看门狗(独立看门狗,窗口看门狗) 的相关文章

  • c语言 (3×3)矩阵转置

    题目描述 写一个函数 使给定的一个二维数组 转置 即行列互换 输入 一个3x3的矩阵 输出 转置后的矩阵 样例输入 1 2 3 4 5 6 7 8 9 样例输出 1 4 7 2 5 8 3 6 9 废话不说还是直接上代码 include
  • 使用STM32CUBEIDE创建工程,点亮LED

    1 创建LED驱动文件 先在工程下新建一个文件夹命名为icode存放驱动程序 然后对每一个外设新建新的驱动文件夹 如驱动LED就新建文件夹led 然后在led文件夹下创建对应的头文件和源文件 即led h和led c 然后编写对应外设的驱动
  • X.509证书的使用

    总结一下如何使用X 509证书来保护我们的设备的数据传输 证书的签发 以下是证书签发的流程 为了更好的演示 我们需要分别创建两个根证书 并且用每个根证书来颁发一个客户端证书 这两个根证书分别为root 1 crt以及root 2 crt 对
  • Java上传下载ftp文件

    在Java中连接FTP服务器可以使用Apache Commons Net库提供的FTPClient类 以下是一个简单的示例代码 演示如何连接到FTP服务器 进行文件上传和下载操作 import org apache commons net

随机推荐

  • 【Windows上同时安装两个不同版本MYSQL】MySQL安装教程--5.7和8.0版本

    一 MySQL官网下载对应版本的zip文件 最新版本8 0 34下载链接 https dev mysql com downloads mysql MySQL 5 7下载链接 https downloads mysql com archive
  • vue中使用百度地图自定义信息窗口

    场景 点击地图上的标注的时候 希望可以显示自定义的信息弹窗 具体效果如下 注意 如果只是简单显示信息 则使用InfoWindow信息窗口或者标注本身的title属性即可 想自定义就使用infoBox自定义信息窗口工具 效果 效果图是GIF图
  • 【满分】【华为OD机试真题2023B卷 JS】矩阵最大值

    华为OD2023 B卷 机试题库全覆盖 刷题指南点这里 矩阵最大值 知识点矩阵数组 时间限制 1s 空间限制 32MB 限定语言 不限 题目描述 给定一个仅包含0和1的N N二维矩阵 请计算二维矩阵的最大值 计算规则如下 1 每行元素按下标
  • startx analyze

    1 xinit 在说明startx之前 我想我们应该先了解一下xinit 因为startx就是通过调用xinit启动X的 1 1 功能 当我们安装了Ubuntu后 默认就已经安装了xinit 它位于 usr bin下 xinit是一个二进制
  • RabbitMQ(四)消息Ack确认机制

    RabbitMQ 四 消息Ack确认机制 确认种类 RabbitMQ的消息确认有两种 消息发送确认 这种是用来确认生产者将消息发送给交换器 交换器传递给队列的过程中 消息是否成功投递 发送确认分为两步 一是确认是否到达交换器 二是确认是否到
  • AS 从SVN转向Git

    之前的项目都是用SVN 感觉SVN 还是挺不错的 但接触了Git后 才发现长江后浪推前浪 前浪死在沙滩上 果断抛弃了SVN 转向git的怀抱 虽然遇到了很多问题 但在同事的帮助下 至少能上传和check了 之后遇到git上的问题后 在写文章
  • js从数组中提取自己所需的数据

    1 场景一 人员选择相关问题 场景一 从人员选择数据中 提取已选的人员信息 selectedList为已选择的人员信息 只有id groupInfo接口返回的原始数据 所有人员信息 需要找出已选择的人员信息的具体信息 const group
  • 使用RBAC模型构建动态路由权限,交由前端动态渲染路由。

    根据RBAC模型生成动态路由并交给前端渲染 什么是RBAC模型 简单的RBAC模型数据库设计 后端处理动态的路由表信息 前端渲染路由的细节与注意 什么是RBAC模型 RBAC Role Based Access Control 模型是一种访
  • C++0基础教程

    还在苦恼找不到C 的教程吗 这篇文章搞定C 基础内容 前言 C 是一门编译型语言 是面向对象的 C 对语法的要求较高 且记忆量较大 但其运行速度较快 且编译过后是 exe的文件 可以直接运行 因此深受青睐 目录 前言 准备工作 C 源码文件
  • Chap3_数据预处理

    数据预处理 什么是数据预处理 数据分析算法的设计与选择需要考虑被处理数据的特征 数据质量过低或数据的形态不符合算法需求时 需要进行数据预处理工作 数据预处理是指对数据进行正式处理 计算 之前 根据后续数据计算的需求对原始数据集进行审计 清洗
  • 数据仓库建设及数据治理总结

    在谈数仓之前 先来看下面几个问题 数仓为什么要分层 用空间换时间 通过大量的预处理来提升应用系统的用户体验 效率 因此数据仓库会存在大量冗余的数据 不分层的话 如果源业务系统的业务规则发生变化将会影响整个数据清洗过程 工作量巨大 通过数据分
  • python使用 itchat结合图灵微信群机器人回复源码

    突然来了下兴致 又弄了个前几个月弄的微信群机器人 功能有好友之间的回复 群艾特后的回复 下面是源码 有更多的请看其他博文 coding utf 8 Time 2018 11 5 12 17 Author 蛇崽 Email 643435675
  • Qt::WindowFlags

    查了些资料 整理了一下 以备查询 枚举类型 Qt WindowFlags低位的一个字节用于定义窗口部件的窗口类型 Qt WindowFlags的高位字节定义了窗口提示 窗口提示能够进行位或操作 例如 Qt WindowContextHelp
  • K210学习篇(八)在MaixHub训练模型

    前言 本文着重于如何使用K210拍摄图片 并将图片上传到MaixHub平台进行模型训练 补充一下一些经验心得 比如一些训练参数的设置 在我们训练模型之前 我们需要获取一些数据集 其实也就是需要识别的物体图片 这里记得我们在获取数据集的时候
  • 获取shell返回值

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 使用command 二 使用function 总结 前言 shell获取返回值的方法有多种 这里介绍两种 第一种是直接执行command然后获取返回值 第
  • js歌词滚动效果

    目录 效果图展示 一 素材准备 1 歌词数据data js 借鉴了网上copy下来的歌词模板 2 图片准备 设置title效果 3 音频文件准备 二 html块 拓展 标签属性 三 设置scss样式 四 逻辑js块 拓展 使用到的audio
  • 史蒂夫科恩_科特琳·科恩范围

    史蒂夫科恩 学习Android开发 Learning Android Development If you are familiar with Dagger 2 you probably know that Scope an importa
  • STM32-I2C --- 通过IO口模拟

    I2C 通过IO口模拟 1 I2C介绍 I2C两根线 一根时钟线 SCL 一根信号线 SDA 数据传输时 时钟线信号为低电平时 数据线电平才允许变化 起始和停止位控制时 时钟线信号为高电平 数据线由高向低变化为起始信号 数据线由低向高变化为
  • NOT 函数

    前言 NOT 函数是用于对参数值求反的一种 Excel 函数 当要确保一个值不等于某一特定值时 可以使用 NOT 函数 简言之 就是当参数值为 TRUE 时 NOT 函数返回的结果恰与之相反 结果为 FALSE 比如 NOT 2 2 4 由
  • stm32-看门狗(独立看门狗,窗口看门狗)

    基于野火教程的看门狗 实验器材 stm32c8t6 LED灯 按键一个 实验一 独立看门狗 1 实验原理 2 实验代码讲解 3 实验现象 实验二 窗口看门狗 1 实验原理 2 实验代码讲解 3 实验现象 在进入正题之前 我们先了解一下什么是