当前位置: 首页 > article >正文

窗口门狗实验(WWDG)实验【学习】

使用 窗口看门狗的中断功能来喂狗, 通过 DS0和 DS1提示程序的运行状态。

11.1窗口看门狗简介

窗口看门狗(WWDG)通常被用来监测由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。除非递减计数器的值在T6位 WWDG-->CR的第六位)
变成 0前被刷新,看门狗电路在达到预置的时间周期时,会产生一个 MCU复位。

在递减计数器达到窗口 配置 寄存器 (WWDG-->CFR)数值之前,如果 7位的递减计数器数值 (在控制寄存器中 )被刷新, 那么也将产生一个 MCU复位。这表明递减计数器需要在一个有限的时间窗口中被刷新。 

上窗口值 W[6:0】 是由用户自己设定的,根据实际要求来设计窗口值

窗口看门狗的超时公式如下:
Twwdg=(4096××2^WDGTB××(T[5:0]+1)) /Fpclk1;

其中
Twwdg: WWDG超时时间 (单位为 ms
Fpclk1 :APB1的时钟频率(单位为 Khz
WDGTB :WWDG的预分频系数
T[5:0]:窗口看门狗的计数器低 6位

最大超时值:因为是T[5:0],共六位,第六位变成0之前被刷新,即值为0x20,0x3f-0x20=0x1f

最小超时值:T{5:0}=0

介绍窗口看门狗的3个寄存器

1.控制寄存器                WWDG_CR

                低八位有效, T[6 0]用来存储看门狗的计数器值,随时更新的,每个 窗口看门狗计数 周期( 4096 × 2^ WDGTB)减 1。当该计数器的值从 0X40变为 0X3F的时候,将产生看门狗复位。

                WDGA位则是看门狗的激活位,该位由软件置 1,以启动看门狗,并且一定要注意的是该位一旦设置,就只能在硬件复位后才能清零了。

2.配置寄存器     WWDG_CFR

    

该位中的EWI是提前唤醒中断,也就是在快要产生复位的前一段时间 T[6:0]=0X40 来提醒我们,需要进行喂狗了,否则将复位!

因此,我们一般用该位来设置中断,当窗口看门狗的计数器值减到 0X40的时候,如果该位设置,并开启了中断,则会产生中断,我们可以在中断里面 向 WWDG_CR重新写入计数器的值,来达到喂狗的目的。

注意这里在进入中断后, 必须 在不大于 1个窗口看门狗计数周期 的时间( 在 PCLK1频率 为 36M且 WDGTB为 0的 条件下该时间为 113us)内重新写 WWDG_CR,否则,看门狗将产 生复位!

3.状态寄存器 WWDG_SR

该寄存器用来记录当前是否有提前唤醒的标志。该寄存器仅有位 0有效,其他都是保留位。当计数器值达到40h时,此位由硬件置 1。它必须通过软件写 0来清除。对此位写 1无效。 即使 中断未被使能, 在计数器的值达到 0X40,此位也会被置1

如何启用窗口看门狗

1.使能WWDG时钟(wwdg无独立时钟)

__HAL_RCC_WWDG_CLK_ENABLE(); //使能窗口看门狗时钟

2.设置窗口值,分频数和计数器初始值

函数 HAL_WWDG_Init来设置的。该函数声明如下:

HAL_StatusTypeDef       HAL_WWDG_Init(WWDG_HandleTypeDef *hwwdg);

        typedef struct

        {

        WWDG_TypeDef *Instance;

        WWDG_InitTypeDef Init;

        }

        WWDG_HandleTypeDef;

typedef struct

        {

                uint32_t Prescaler; //预分频系数
                uint32_t Window; //窗口值
                uint32_t Counter; //计数器值
                uint32_t EWIMode ; //是否启用 WWDG早期唤醒中断
        }

        WWDG_InitTypeDef;

函数 HAL_WWDG_Init的使用范例如下:

WWDG_HandleTypeDef WWDG_Handler; //窗口看门狗句柄
WWDG_Handler.Instance=WWDG; //窗口看门狗
WWDG_Handler.Init.Prescaler=WWDG_PRESCALER_8; //设置分频系数为 8 WWDG_Handler.Init.Window=0X5F; //设置窗口值 0X5F

WWDG_Handler.Init.Counter=0x7F; //设置计数器值 0x7F

HAL_WWDG_Init(&WWDG_Handler); //初始化 WWDG

3.使能中断通道并配置优先级(如果开启了 WWDG中断)

HAL_NVIC_SetPriority(WWDG_IRQn,2,3); //抢占优先级 2,子优先级为 3 HAL_NVIC_EnableIRQ(WWDG_IRQn); //使能窗口看门狗中断

4.编写中断服务函数

在最后,还是要编写窗口看门狗的中断服务函数,通过该函数来喂狗,喂狗要快,否则当
窗口看门狗计数器值减到 0X3F的时候,就会引起软复位了。在中断服务函数里面也要将状态
寄存器的 EWIF位清空。

窗口看门狗中断服务函数为:
        void WWDG_IRQHandler(void);
在HAL库中,喂狗函数为:
        HAL_StatusTypeDef HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg);
WWDG的喂狗操作实际就是往 CR寄存器重写计数器值。

5.重写窗口看门狗唤醒中断处理回调函数

跟串口和外部中断 一样, HAL库定义了一个中断处理共用函数HAL_WWDG_IRQHandler,我们在 WWDG中断服务函数中会调用该函数。同时该函数内部,会经过一系列判断,最后调用回调函数 HAL_WWDG_WakeupCallback,所以提前唤醒中断逻辑


我们一般些在回调函数 HAL_WWDG_WakeupCallback中。 回调函数声明为:
void HAL_WWDG_EarlyWakeupCallback (WWDG_HandleTypeDef* hwwdg);

完成了以上5个步骤之后,我们就可以使用 STM32F1的窗口看门狗了。这一 章 的实验,
我们将通过 DS0来指示 STM32F1是否被复位了,如果被复位了就会点亮 300ms。 DS1用来指
示中断喂狗,每次中断喂狗翻转一次。

11.2硬件设计

本实验用到的硬件资源有:
1) 指示灯 DS0和 DS1
2) 窗口看门狗
其中指示灯前面介绍过了,窗口看门狗属于STM32的内部资源,只需要软件设置好即可
正常工作。我们通过 DS0和 DS1来指示 STM32的复位情况和窗口看门狗的喂狗情况。

11.3软件设计

这里,我们在之前的IWDG看门狗实例内增添部分代码来实现

首先打开上次的工程,然后在 wdg.c加入如下代码(之前代码保留):

WWDG_HandleTypeDef     WWDG_Handler; //窗口看门狗句柄
//保存 WWDG计数器的设置值,默认为最大
//u8 WWDG_CNT=0X7F; //初始化窗口看门狗
//tr :T[6:0],计数器值
//wr :W[6:0],窗口值
//fprer:分频系数( WDGTB)),仅最低 2位有效
//Fwwdg=PCLK1/(4096*2^fprer). 一般 PCLK1=42Mhz

void WWDG_Init(u8 tr,u8 wr,u32 fprer)

{

WWDG_Handler.Instance=WWDG;

WWDG_Handler.Init.Prescaler=fprer; //设置分频系数
WWDG_Handler.Init.Window=wr; //设置窗口值

WWDG_Handler.Init.Counter=tr; //设置计数器值
WWDG_Handler.Init.EWIMode=WWDG_EWI_ENABLE; //使能窗口看门狗提前唤醒中断
HAL_WWDG_Init(&WWDG_Handler); //初始化 WWDG

}

//WWDG底层驱动,时钟配置,中断配置
//此函数会被 HAL_WWDG_Init()调用
//hwwdg:窗口看门狗句柄


void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg)

{

__HAL_RCC_WWDG_CLK_ENABLE(); //使能窗口看门狗时钟
HAL_NVIC_SetPriority(WWDG_IRQn,2,3); //抢占优先级 2,子优先级为 3 HAL_NVIC_EnableIRQ(WWDG_IRQn); //使能窗口看门狗中断
}

//窗口看门狗中断服务函数
void WWDG_IRQHandler(void)

{

HAL_WWDG_IRQHandler(&WWDG_Handler);

//调用 WWDG共用中断处理函数
} //中断服务函数处理过程
//此函数会被 HAL_WWDG_IRQHandler()调用


void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef* hwwdg)

{

HAL_WWDG_Refresh(&WWDG_Handler);//更新窗口看门狗值
LED1=!LED1;

}

主函数

int main(void) {

HAL_Init(); //初始化 HAL库
……//此处省略部分初始化代码
LED0=0; //点亮 LED0

delay_ms(300); //延时 300ms再初始化看门狗 ,LED0的变化 "可见 " WWDG_Init(0X7F,0X5F,WWDG_PRESCALER_8);

//计数器值为 7F,窗口寄存器为 5F,分频数为 8

while(1)

{

LED0=1; //熄灭 LED灯
}

}

11.4 下载验证


将代码下载到MiniSTM32后,可以看到 DS0亮一下之后熄灭,紧接着 DS1开始不停的闪
烁。每秒钟闪烁 8次左右,和我们预期的一致 ,说明我们的实验是成功的。


http://www.kler.cn/a/509354.html

相关文章:

  • v2富文本框封装 @wangeditor/editor-for-vue
  • MongoDB 学习指南:深入探索非关系型数据库
  • springboot多环境配置
  • 基于微信小程序的摄影竞赛系统设计与实现(LW+源码+讲解)
  • 深度学习中的卷积和反卷积(四)——卷积和反卷积的梯度
  • C++实现设计模式---外观模式 (Facade)
  • 【高阶数据结构】位图(BitMap)
  • OSPF - 路由过滤的几种方法
  • C++/QT环境下图像在窗口下等比例渲染绘制
  • OpenEuler学习笔记(一):常见命令
  • UDP 单播、多播、广播:原理、实践
  • 【C++笔记】红黑树封装map和set深度剖析
  • 高性能、并发安全的 Go 嵌入式缓存库 如何使用?
  • 浅谈云计算22 | Kubernetes容器编排引擎
  • ASP.NET Core全球化与本地化:打造多语言应用
  • vulnhub靶场【jangow】靶机,考察反弹shell的流量及端口的选择
  • Transformer之Encoder
  • 如何在openEuler中编译安装Apache HTTP Server并设置服务管理(含Systemd和Init脚本)
  • 【Linux】线程全解:概念、操作、互斥与同步机制、线程池实现
  • linux下springboot项目nohup日志或tomcat日志切割处理方案
  • Redis集群部署详解:主从复制、Sentinel哨兵模式与Cluster集群的工作原理与配置
  • leetcode707-设计链表
  • 电脑风扇声音大怎么办? 原因及解决方法
  • github 端口22 超时问题解决
  • AWS物联网连接的数据记录器在冰川环境中的性能比较:Campbell CR1000X与ESP32开源
  • 【react】使用antd Table渲染数据遇到的报错问题