STM32G474窗口看门狗中断

2024-09-06 16:44

本文主要是介绍STM32G474窗口看门狗中断,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

STM32G474窗口看门狗中断用来演示最后一次喂狗。注意:即使窗口看门狗被禁止,窗口看门狗的"递减计数器"也会继续递减计数。

1、窗口看门狗复位的条件
1)、将"控制寄存器WWDG_CR"中的WDGA=1,激活"窗口看门狗计数器等于0x3F"时,则产生复位
2)、装载"窗口看门狗的计数器值"大于"窗口看门狗window寄存器的值",则产生复位。
3)、窗口看门狗的"提前唤醒中断EWI=1",且"窗口看门狗递减计数器的值"达到0x40时,则产生EWI中断。
其中断处理程序处理完后,则产生复位。
4)、装载"窗口看门狗计数器值"的条件:

2、喂狗的条件
递减计数器的值小于或等于窗口寄存器的数值,并且大于0x3F时,才可以向"窗口看门狗计数器值"写入新值,否则会引起CPU复位。

3、本程序配置计算


1)、窗口看门狗时钟计数器周期:
(4096 * WWDG_PRESCALER_128) / (PCLK1 / 1000)
=4096*128/(170000000/1000)
= 3.084 ms

2)、窗口看门狗溢出时间:
(0x7F + 1) * 3.084
=(127+1) * 3.084
=394.752ms
在窗口看门狗计数器被设置为0x7F后,窗口看门狗将在394.752毫秒后,如果没有喂狗,就令CPU复位;

3)、允许写入窗口看门狗计数器时间:
(0x7F - 0x50 + 1) * 3.084
=(127-80+1) * 3.084
= 148.032 ms

窗口看门狗计数器到达0x40:
(0x7F - 0x40) * 3.084 -1
=(127-64) * 3.084
= 193.292 ms


注意:若在148ms和193ms内喂狗,即在窗口时间内喂狗,WWDG就不会令CPU复位

4、窗口看门狗的作用

用来约束“某段代码”必须在规定时间内完成,检测软件是否产生异常。
如果在规定时间内,这段代码还处理完成,导致窗口看门狗来不及喂狗,从而引起CPU复位。
进入中断后,可以处理紧急事务,如保存重要数据,可以重要数据写入EEPROM。
记住:WWDG中断是给程序最后一次喂狗的机会,但不能在窗口看门狗中断里喂狗,否则,窗口看门狗就不能引起CPU复位了

5、WWDG.c程序

#include "WWDG.h"
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "LED.h"
#include "delay.h"uint32_t COMP_Init(void);
void WWDG_Counter_Reload(void);
void SysRstSrcRecord_WWDG(void);uint32_t WWDG_Init(void)
{WWDG_HandleTypeDef hwwdg;uint32_t timeoutvalue = 0;uint32_t pclk1 = 0;uint32_t wdgtb = 0;uint32_t WWDG_delay_Start;uint32_t WWDG_delay_End;__HAL_RCC_WWDG_CLK_ENABLE();//使能WWDG时钟hwwdg.Instance = WWDG;                     //选择WWDGhwwdg.Init.Prescaler = WWDG_PRESCALER_128; //窗口看门狗的预分频器值:选择128分频hwwdg.Init.Window = WWDG_Window_Value;//窗口看门狗窗口值(7位):   0x40~0x7f//这里设置WWDG_CFR寄存器bit6:0(W[6:0]),令W[6:0]=0x0x50hwwdg.Init.Counter = 0x7F;//窗口看门狗计数器值(7位): 0x7F//WWDG_CR寄存器bit6:0(T[6:0]),令T[6:0]=0x7Fhwwdg.Init.EWIMode = WWDG_EWI_DISABLE;     //窗口看门狗计数器值到达0x40时不会产生中断HAL_WWDG_Init(&hwwdg);timeoutvalue=(hwwdg.Init.Counter - hwwdg.Init.Window) + 1;//计算"窗口看门狗计数器值"和"窗口看门狗窗口值"的差//计算“喂狗需要多少个WWDG计数器时钟”pclk1 = HAL_RCC_GetPCLK1Freq();//获取PCLK1的值wdgtb = ( 1 << ( (hwwdg.Init.Prescaler) >> WWDG_CFR_WDGTB_Pos) );//获取WWDG的分频值,2^WDGTB[1:0]//WWDG_CFR寄存器bit13:11(WDGTB[2:0]),WDGTB[2:0]=111b,表示128分频//2^7=128timeoutvalue = ( (4096 * wdgtb * timeoutvalue) / (pclk1 / 1000) );//计算超时时间WWDG_delay_Start=timeoutvalue;//单位为“毫秒”//  NVIC_SetPriority(WWDG_IRQn,0x02);//设置"窗口看门提前唤醒中断"优先级为0x02,WWDG_IRQn表示中断源为"提前唤醒"
//  NVIC_EnableIRQ(WWDG_IRQn);//使能"窗口看门提前唤醒中断"HAL_NVIC_SetPriority(WWDG_IRQn, 0x02, 0);//设置"窗口看门提前唤醒中断"优先级为0x02,0无意义.WWDG_IRQn表示中断源为"提前唤醒"HAL_NVIC_EnableIRQ(WWDG_IRQn);//使能"窗口看门提前唤醒中断"__HAL_WWDG_ENABLE_IT(&hwwdg,WWDG_IT_EWI);//计算允许写WWDG的时间范围/timeoutvalue= hwwdg.Init.Counter - 0x40;timeoutvalue = ( (4096 * wdgtb * timeoutvalue) / (pclk1 / 1000) );WWDG_delay_End=timeoutvalue-1;//单位为“毫秒”printf("Feed wwdg time range: from %ums to %ums\r\n",WWDG_delay_Start,WWDG_delay_End);return WWDG_delay_Start;//返回"窗口看门狗的复位时间",单位为毫秒
}//函数功能:喂狗
void WWDG_Counter_Reload(void)
{WRITE_REG(WWDG->CR,0x7F);//WWDG_CR寄存器bit6:0(T[6:0]),令T[6:0]=0x7F//Write to WWDG CR the WWDG Counter value to refresh with 0x7F
}//(__FLAG__)=RCC_FLAG_HSIRDY,若返回1,表示HSI振荡器已经准备好
//(__FLAG__)=RCC_FLAG_HSERDY,若返回1,表示HSE振荡器已经准备好
//(__FLAG__)=RCC_FLAG_PLLRDY,若返回1,表示Main PLL时钟已经准备好
//(__FLAG__)=RCC_FLAG_LSERDY,若返回1,表示LSE振荡器已经准备好
//(__FLAG__)=RCC_FLAG_HSI48RDY
//(__FLAG__)=RCC_FLAG_LSECSSD
//(__FLAG__)=RCC_FLAG_LSIRDY,若返回1,表示LSI振荡器已经准备好
//(__FLAG__)=RCC_FLAG_BORRST,若返回1,表示是由BOR or POR/PDR产生复位
//(__FLAG__)=RCC_FLAG_OBLRST,若返回1,表示是由Option byte loader产生复位
//(__FLAG__)=RCC_FLAG_PINRST,若返回1,表示是由复位引脚产生复位
//(__FLAG__)=RCC_FLAG_SFTRST,若返回1,表示是由软件产生复位
//(__FLAG__)=RCC_FLAG_IWDGRST,若返回1,表示是由独立看门狗产生复位
//(__FLAG__)=RCC_FLAG_WWDGRST,若返回1,表示是由窗口看门狗产生复位
//(__FLAG__)=RCC_FLAG_LPWRRST
//函数功能:打印CPU复位原因
void SysRstSrcRecord_WWDG(void)
{uint8_t i;uint8_t Reset_Buffer[11];for(i=0;i<11;i++) Reset_Buffer[i]=0;//清除Reset_Buffer[0] = __HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY);//读取"内部部24MHz时钟源稳定标志"Reset_Buffer[1] = __HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY);//读取"外部4~32MHz时钟源稳定标志"Reset_Buffer[2] = __HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY);  //读取"PLL时钟稳定标志"Reset_Buffer[3] = __HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY);//读取"外部32.768KHz的时钟源稳定标志"Reset_Buffer[4] = __HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY);//读取"内部RC的32KHz时钟源稳定标志"Reset_Buffer[5] = __HAL_RCC_GET_FLAG(RCC_FLAG_PINRST);    //读取"外部引脚复位标志"Reset_Buffer[6] = __HAL_RCC_GET_FLAG(RCC_FLAG_BORRST);   //读取"BOR/POR/PDR复位标志"Reset_Buffer[7] = __HAL_RCC_GET_FLAG(RCC_FLAG_SFTRST);    //读取"软件复位标志"Reset_Buffer[8] = __HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST); //读取"独立看门狗定时器复位标志"Reset_Buffer[9] = __HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST); //读取"窗口看门狗定时器复位标志"Reset_Buffer[10] = __HAL_RCC_GET_FLAG(RCC_FLAG_OBLRST);   //读取"Option byte loader复位标志"if( Reset_Buffer[0] ) printf("\r\nHSI OK!\r\n");if( Reset_Buffer[1] ) printf("HSE OK!\r\n");if( Reset_Buffer[2] ) printf("PLL OK!\r\n");if( Reset_Buffer[3] ) printf("LXTAL OK!\r\n");if( Reset_Buffer[4] ) printf("LSI OK!\r\n");if( Reset_Buffer[5] ) printf("PIN reset!\r\n");if( Reset_Buffer[6] ) printf("POR reset!\r\n");if( Reset_Buffer[7] ) printf("SWR reset!\r\n");if( Reset_Buffer[8] ) printf("IWDG reset!\r\n");if( Reset_Buffer[9] ) printf("WWDG reset!\r\n");if( Reset_Buffer[10] ) printf("Option byte loader reset!\r\n");
}//函数功能:"窗口看门提前唤醒"中断服务程序
//"窗口看门狗递减计数器的值"达到0x40时,则产生EWI中断
void WWDG_IRQHandler(void)
{if (_HAL_WWDG_GET_FLAG(WWDG, WWDG_FLAG_EWIF) != RESET){_HAL_WWDG_CLEAR_FLAG(WWDG, WWDG_FLAG_EWIF);//将"窗口看门狗状态寄存器WWDG_SR"中的EWIF=0,清除"提前唤醒中断标志位"//HAL_WWDG_EarlyWakeupCallback函数开始///
//		WWDG_Counter_Reload();//在"窗口看门狗递减计数器的值"没有到0x3F前喂狗,不会引起看门狗复位//不能在中断里喂狗,否则,窗口看门狗就不能引起CPU复位了。LED1_On();delay_ms(20);
//HAL_WWDG_EarlyWakeupCallback函数结束///}
}

6、WWDG.h程序

#ifndef __WWDG_H__
#define __WWDG_H__#include "stm32g4xx_hal.h"
//使能int8_t,int16_t,int32_t,int64_t
//使能uint8_t,uint16_t,uint32_t,uint64_t#define WWDG_Window_Value  0x50#define Get_WWDG_Counter(__INSTANCE__)  ( (__INSTANCE__)->CR & (~WWDG_CR_WDGA) )
//读窗口计数器的值#define _HAL_WWDG_GET_FLAG(__INSTANCE__, __FLAG__) (((__INSTANCE__)->SR & (__FLAG__)) == (__FLAG__))
//(__FLAG__)=WWDG_FLAG_EWIF,读"窗口看门狗状态寄存器WWDG_SR"中的EWIF
//若EWIF=1,窗口看门狗计数器值等于0x40,建立"提前唤醒标志"#define _HAL_WWDG_CLEAR_FLAG(__INSTANCE__, __FLAG__) (((__INSTANCE__)->SR) = ~(__FLAG__))
//(__FLAG__)=WWDG_FLAG_EWIF,将"窗口看门狗状态寄存器WWDG_SR"中的EWIF=0,清除"提前唤醒中断标志位"extern uint32_t WWDG_Init(void);
extern void WWDG_Counter_Reload(void);
extern void SysRstSrcRecord_WWDG(void);#endif /*__ WWDG_H__ */

7、main.c程序

#include "main.h"
//#include "cmsis_os.h"
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "sys.h"
#include "Clock_Config.h"
#include "WWDG.h"
#include "LED.h"
#include "delay.h"
#include "USART1.h"const char CPU_Reset_REG[]="\r\nCPU reset!\r\n";
int main(void)
{uint8_t cnt;uint32_t WWDG_delay;STACK_Init();HAL_Init();//复位所有的外设//初始化FLASH接口//将SysTick定时器配置1ms中断//因为“HRTIM定时器A”的中断优先级为0,所以需要在“stm32g4xx_hal_conf.h”,将TICK_INT_PRIORITY定义为1,设置SysTick中断优先级为1SystemClock_Config();//Configure the system clockHAL_Delay(500);USART1_Init(115200);printf("%s",CPU_Reset_REG);Print_HCLK_PCLK1_PCLK2();SysRstSrcRecord_WWDG();delay_init();delay_ms(1000);LED_Init();//配置PC13为输出,无上拉或下拉,输出速度为5MHzdelay_ms(500);WWDG_delay=WWDG_Init();cnt=0;while (1){
//		delay_ms(194); //WWDG会令CPU复位
//		delay_ms(193); //因为在窗口时间内喂狗,所以WWDG不会令CPU复位delay_ms(WWDG_delay); //因为在窗口时间内喂狗,所以WWDG不会令CPU复位if( Get_WWDG_Counter(WWDG) <= WWDG_Window_Value)//喂狗时间到WWDG_Counter_Reload();//喂狗cnt++;printf("cnt=%u\r\n",cnt);}
}//函数功能:在发生错误时,将执行此函数。
void Error_Handler(void)
{__disable_irq();while (1){printf("Error\r\n");}
}

8、测试结果

若出现LED亮,则表示进入WWDG中断程序了。 

这篇关于STM32G474窗口看门狗中断的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1142556

相关文章

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

使用JS/Jquery获得父窗口的几个方法(笔记)

<pre name="code" class="javascript">取父窗口的元素方法:$(selector, window.parent.document);那么你取父窗口的父窗口的元素就可以用:$(selector, window.parent.parent.document);如题: $(selector, window.top.document);//获得顶级窗口里面的元素 $(

专题二_滑动窗口_算法专题详细总结

目录 滑动窗口,引入: 滑动窗口,本质:就是同向双指针; 1.⻓度最⼩的⼦数组(medium) 1.解析:给我们一个数组nums,要我们找出最小子数组的和==target,首先想到的就是暴力解法 1)暴力: 2)优化,滑动窗口: 1.进窗口 2.出窗口 3.更新值 2.⽆重复字符的最⻓⼦串(medium) 1)仍然是暴力解法: 2)优化: 进窗口:hash[s[rig

FreeRTOS学习笔记(四)Freertos的中断管理及临界保护

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、Cortex-M 中断管理1.1 中断优先级分组1.2 相关寄存器1.3 相关宏定义1.4 FreeRTOS 开关中断 二、临界段及其保护2.1 taskENTER_CRITICAL( ) 和 taskEXIT_CRITICAL( )2.2 taskENTER_CRITICAL_FROM_ISR( )

hot100刷题第1-9题,三个专题哈希,双指针,滑动窗口

求满足条件的子数组,一般是前缀和、滑动窗口,经常结合哈希表; 区间操作元素,一般是前缀和、差分数组 数组有序,更大概率会用到二分搜索 目前已经掌握一些基本套路,重零刷起leetcode hot 100, 套路题按套路来,非套路题适当参考gpt解法。 一、梦开始的地方, 两数之和 class Solution:#注意要返回的是数组下标def twoSum(self, nums: Lis

主窗口的设计与开发(二)

主窗口的设计与开发(二) 前言         在上一集当中,我们完成了主窗口的初始化,主窗口包括了左中右三个区域。我们还完成了对左窗口的初始化,左窗口包括了用户头像、会话标签页按钮、好友标签页按钮以及好友申请标签页按钮。对于切换每个标签页,我们还做了初始化信号槽的内容。最后我们将整个MainWidget类设置为单例模式。         那么这一集我们将继续完成主窗口的设计与开发,这一集我

Cortex-A7:ARM官方推荐的嵌套中断实现机制

0 参考资料 ARM Cortex-A(armV7)编程手册V4.0.pdf ARM体系结构与编程第2版 1 前言 Cortex-M系列内核MCU中断硬件原生支持嵌套中断,开发者不需要为了实现嵌套中断而进行额外的工作。但在Cortex-A7中,硬件原生是不支持嵌套中断的,这从Cortex-A7中断向量表中仅为外部中断设置了一个中断向量可以看出。本文介绍ARM官方推荐使用的嵌套中断实现机

QtC++截图支持窗口获取

介绍 在截图工具中你会发现,接触到窗口后会自动圈出目标窗口,个别强大一点的还能进行元素识别可以自动圈出元素,那么今天简单分析一下QTc++如何获取窗口并圈出当前鼠标下的窗口。 介绍1.如何获取所有窗口2.比较函数3.实现窗口判断 结尾 1.如何获取所有窗口 1.我们需要调用windows接口EnumWindowsProc回调函数来获取所有顶级窗口,需要包含windows.

运行.bat文件,如何在Dos窗口里面得到该文件的路径

把java代码打包成.jar文件,编写一个.bat文件,执行该文件,编译.jar包;(.bat,.jar放在同一个文件夹下) 运行.bat文件,如何在Dos窗口里面得到该文件的路径,并运行.jar文件: echo 当前盘符:%~d0 echo 当前路径:%cd% echo 当前执行命令行:%0 echo 当前bat文件路径:%~dp0 echo 当前bat文件短路径:%~sdp0 nc

类codepen的实现可拖拽窗口demo

首先说下思想 flex或者其他布局方式,实现左右分割布局,主盒子宽度100%,左右布局中包含一个分割条(可在布局容器中,也可以单独定义)为分隔条绑定鼠标点击事件,为document绑定鼠标移动事件和鼠标放开事件,通过监听鼠标移动事件和上一个状态保存下来的鼠标位置作对比,判断当前鼠标移动方向(往左还是往右)然后计算当前鼠标位置和鼠标点击位置的距离,来计算左右容器的变化,然后通过dom的方式设置宽度