四、GD32 MCU 常见外设介绍(9)9.FWDG 模块介绍

9.1.FWDG 简介

本章我们主要分析独立看门狗(FWDG)的功能框图和它的应用。独立看门狗用通俗一点的话来解释就是一个12位的递减计数器,当计数器的值从某个值一直减到0的时候,系统就会产生一个复位信号,即FWDGTRSTF。如果在计数没减到0之前,刷新了计数器的值的话,那么就不会产生复位信号,这个动作就是我们经常说的喂狗。看门狗功能由 VDD 电压域供电,在停止模式和待机模式下仍能工作。独立看门狗定时器有独立的时钟源(IRC40K) 。 即使主时钟失效, FWDGT依然 能保持正常工作状态, 适用于需要独立环境且对计时精度要求不高的场合。

9.2.GD32 FWDG 外设原理简介

因篇幅有限,本文无法详细介绍GD32所有系列FWDG外设接口,下面以GD32F30x为列,着重介绍下GD32F30x的FWDG外设简介和结构框图,后介绍下各个系列的差异。

GD32 FWDG 主要特性

◼ 自由运行的12位向下计数器;

◼ 如果看门狗定时器被使能,那么当向下计数器的值达到0时产生系统复位;

◼ 独立时钟源,独立看门狗定时器在主时钟故障(例如待机和深度睡眠模式下)时仍能工作;

◼ 独立看门狗定时器硬件控制位,可以用来控制是否在上电时自动启动独立看门狗定时器;

◼ 可以配置独立看门狗定时器在调试模式下选择停止还是继续工作。

FWDG时钟:如FWDG框图的①所示, FWDG的时钟由独立的RC振荡器IRC40K提供,即使主时钟发生故障它仍然有效,非常独立。IRC的频率根据温度和工作场合会有一定的漂移,我们一般取40KHZ,所以FWDG的定时时间并不一定非常精确,只适用于对时间精度要求相对较低的场合。

计数器时钟:如FWDG框图的②所示, 递减计数器的时钟由IRC40K经过一个8位的预分频器得到,我们可以操作预分频器寄存器FWDG_PSC来设置分频因子,分频因子可以是:[4,8,16,32,64,128,256]。

计数器:如图 0-28 FWDG框图的③所示, FWDG的计数器是一个12位的递减计数器,最大值为0XFFF,当计数器减到0时,会产生一个复位信号: FWDGTRSTF,让程序重新启动运行,如果在计数器减到0之前刷新了计数器的值的话,就不会产生复位信号,重新刷新计数器值的这个动作我们俗称喂狗。

重装载寄存器:如FWDG框图的④所示, 重装载寄存器是一个12位的寄存器,里面装着要刷新到计数器的值,这个值的大小决定着FWDG的溢出时间。超时时间Tout = (42^prv) / 40 rlv (s) ,prv是预分频器寄存器的值,rlv是重装载寄存器的值。

控制寄存器:如FWDG框图的⑤所示, 控制寄存器FWDG_CTL可以说是独立看门狗的一个控制寄存器,主要有三种控制方式,往这个寄存器写入下面三个不同的值有不同的效果。具体如下表控制寄存器取值枚举

 状态寄存器:如FWDG框图的⑥所示, 状态寄存器STAT只有位0:PUD和位1:RUD有效,这两位只能由硬件操作,软件操作不了。RUD:看门狗计数器重装载值更新,硬件置1表示重装载值的更新正在进行中,更新完毕之后由硬件清0。PUD: 看门狗预分频值更新,硬件置‘1‘指示预分频值的更新正在进行中,当更新完成后,由硬件清0。所以只有当RUD/PUD等于0的时候才可以更新重装载寄存器/预分频寄存器。

注意

  1. 如果在选项字节中打开了“硬件看门狗定时器”功能,那么在上电的时候看门狗定时器就被自动打开。为了避免系统复位,软件应该在计数器达到0x000之前重装载计数器;

  2. 如果DBG控制寄存器0(DBG_CTL0) 中的FWDGT_HOLD位被清0,即使Cortex®-M4内核停止(调试模式下) 独立看门狗定时器依然工作。如果FWDGT_HOLD位置1,独立看门狗定时器将在调试模式下停止工作。

各系列 FWDG 功能差异

F4xx系例FWDG时钟为32K,因此要注意FWDG的定时时间。

9.3.硬件连接说明

FWDG属于单片机内部资源,不需要外部电路,需要一个外部的按键和LED,通过按键来喂狗,喂狗成功LED亮,喂狗失败,程序重启,LED灭一次。

9.4.软件配置说明

本小节讲解FWDG_Example例程中FWDG模块的实验讲解,主要包括FWDG配置函数、FWDG喂狗函数、主函数介绍以及运行结果。

FWDG 配置函数

外设时钟配置

外设时钟配置如代码清单FWDG例程时钟配置所示,在GD32全系列MCU中需打开GPIOA(LED)的时钟,另外,在GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X || GD32F1X0 || GD32F3X0 || GD32E230中需要打开IRC40K,GD32F4XX中需要打开IRC32K。

void rcu_config(void)
{
#if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X || GD32F1X0 || GD32F4XX || GD32F3X0 || 
GD32E230rcu_periph_clock_enable(RCU_GPIOA);
#if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X || GD32F1X0 || GD32F3X0 || GD32E230
/* enable IRC40K */rcu_osci_on(RCU_IRC40K);/* wait till IRC40K is ready */while(SUCCESS != rcu_osci_stab_wait(RCU_IRC40K)){} 
#elif GD32F4XX 
/* enable IRC32K */rcu_osci_on(RCU_IRC32K);/* wait till IRC32K is ready */while(SUCCESS != rcu_osci_stab_wait(RCU_IRC32K)){} 
#endif
#endif
}

GPIO(LED)引脚配置

GPIO引脚配置如代码清单FWDG例程GPIO(LED)引脚配置所示,GD32F10X、GD32F30X、GD32F20X、GD32E10X系列GPIO配置相同, PA3、PA4作为LED引脚配置为推挽输出模式;GD32F1X0、GD32F4XX、GD32F3X0、GD32E23X系列GPIO配置基本相同。配置完成后将PA3 和PA4拉低。

void gpio_led_config(void)
{
#if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10Xgpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3);
gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4);
#elif defined GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E230gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_3);gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3);
gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_4);gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4);
#endif 
GPIO_BC(GPIOA) = GPIO_PIN_3;
GPIO_BC(GPIOA) = GPIO_PIN_4;
}

按键初始化配置

按键初始化配置如代码清单按键初始化配置所示。本例程中默认使用PA0下降沿进入中断,GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X系列配置基本相同,GD32F1X0 || GD32F3X0系列配置类似。GD32E230中断分组只有抢占优先级没有子优先级。

void key_init(void)
{
#if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X
rcu_periph_clock_enable(RCU_AF);gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
/* enable and set key EXTI interrupt to the lowest priority */
nvic_irq_enable(EXTI0_IRQn, 2U, 0U);
/* connect key EXTI line to key GPIO pin */
gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOA, GPIO_PIN_SOURCE_0);
/* configure key EXTI line */
exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_interrupt_flag_clear(EXTI_0);
#elif defined GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E230
#if defined GD32F1X0 || GD32F3X0 
rcu_periph_clock_enable(RCU_CFGCMP);
/* configure button pin as input */gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE,GPIO_PIN_0);
/* enable and set key EXTI interrupt to the lowest priority */
nvic_irq_enable(EXTI0_1_IRQn, 2U, 0U);
#elif defined GD32E230
rcu_periph_clock_enable(RCU_CFGCMP);
/* configure button pin as input */gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE,GPIO_PIN_0);
/* enable and set key EXTI interrupt to the lowest priority */
nvic_irq_enable(EXTI0_1_IRQn, 2U);
#elif defined GD32F4XX
rcu_periph_clock_enable(RCU_SYSCFG);
/* configure button pin as input */gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE,GPIO_PIN_0);
/* enable and set key EXTI interrupt to the lowest priority */
nvic_irq_enable(EXTI0_IRQn, 2U, 0U);
#endif 
/* connect key EXTI line to key GPIO pin */
syscfg_exti_line_config(EXTI_SOURCE_GPIOA, EXTI_SOURCE_PIN0);
/* configure key EXTI line */
exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_interrupt_flag_clear(EXTI_0);
#endif 
}

FWDG 配置函数

FWDG配置函数如代码清单FWDG配置配置所示。当时钟为40K时,溢出时间Tout =prv/40 rlv (s),prv可以是[4,8,16,32,64,128,256];rlv的取值范围为0~0XFFF。如果我们需要设置1s的超时溢出, prv 可以取 FWDGT_PSC_DIV64 , rlv 取 625 ,即调用 : fwdgt_config(625,FWDGT_PSC_DIV64)。Tout=64/40625=1s。GD32F4XX系列IRC为32K则定时时间1.25s。

void FWDGT_init(void)
{
/* confiure FWDGT counter clock: 40KHz(IRC40K) / 64 = 0.625 KHz GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X
|| GD32F1X0 || GD32F3X0 || GD32E23X*/
/* confiure FWDGT counter clock: 32KHz(IRC32K) / 64 = 0.5 KHz GD32F4XX*/fwdgt_config(625, FWDGT_PSC_DIV64); /* after 1.x seconds to generate a reset */fwdgt_enable();
}

中断喂狗

中断喂狗函数如代码清单中断喂狗所示。当进进入PA0外部中断时执行喂狗函数。

#if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X || GD32F4XX
void EXTI0_IRQHandler(void)
{
/* make sure whether the tamper key EXTI Line is interrupted */if(RESET != exti_interrupt_flag_get(EXTI_0)){/* reload FWDGT counter */fwdgt_counter_reload();}/* clear the interrupt flag bit */exti_interrupt_flag_clear(EXTI_0);
}
#elif defined GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E230
void EXTI0_1_IRQHandler(void)
{
/* make sure whether the tamper key EXTI Line is interrupted */if(RESET != exti_interrupt_flag_get(EXTI_0)){/* reload FWDGT counter */fwdgt_counter_reload();}/* clear the interrupt flag bit */exti_interrupt_flag_clear(EXTI_0);
}
#endif

主函数说明

主函数如代码清单FWDG例程主函数所示,主函数中我们初始化好LED和按键相关的配置,设置FWDG 1s 超时溢出之后,进入while死循环,通过按键来喂狗,如果喂狗成功,则LED2(PA4)点亮,如果喂狗失败的话,系统重启,程序重新执行,当执行到rcu_flag_get函数的时候,则会检测到是FWDG复位,然后让LED1(PA3)亮。如果喂狗一直失败的话,则会一直产生系统复位,加上前面延时的效果,则会看到LED1(PA3)一直闪烁。

int main(void)
{/* peripheral clock enable */rcu_config();
/* config systick */systick_config(); /* GPIO config */gpio_led_config();
key_init();
delay_1ms(500);
FWDGT_init();
/* check if the system has resumed from FWDGT reset */
if(RESET != rcu_flag_get(RCU_FLAG_FWDGTRST)){/* turn on LED1 */
GPIO_BOP(GPIOA) = GPIO_PIN_3;
/* clear the FWDGT reset flag */
rcu_all_reset_flag_clear();
while(1);
}
else{
/* turn on LED2 */
GPIO_BOP(GPIOA) = GPIO_PIN_4;
}while(1)
{
}
}

运行结果

把编译好的程序下载到开发板,在1s的时间内通过按键来不断的喂狗,如果喂狗失败,LED1闪烁。如果一直喂狗成功,则LED2常亮。

9.5.FWDG 使用注意事项

(1) FWDG在Debug仿真时,请将DBG控制寄存器0(DBG_CTL0) 中的FWDGT_HOLD位置1,来关闭FWDG功能。

(2) 没有开启软件看门狗时,程序自动复位,可能在选项字节里开启了硬件看门狗。

(3) 同时使用FWDG、Standby或Deep-sleep模式时,无法喂狗:在reload命令后,硬件清除reload信号之前,进入Deepsleep或者standby模式,会导致后续reload命令无法正常响应。软件保证在reload命令和进入Deepsleep/standby mode的命令中间有3个LXTAL clock(100us)以上的时间间隔。

(4) 由于环境温度影响,独立看门狗定时器超时周期会有些许波动,可以通过校准IRC40K使独立看门狗定时器超时更加精确。

更多GD32 MCU相关咨询:https://www.gd32bbs.com/ 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/875793.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于深度学习算法,支持再学习功能,不断提升系统精准度的智慧地产开源了。

智慧地产视觉监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒,省去繁琐重复的适配流程,实现芯片、算法、应用的全流程组合,从而大大减少企业级应用约95%的开发成本。通过计算机视觉和…

Java基础巩固——JDK 8、9新增接口的特性(接口中定义非抽象方法、静态方法和私有方法)

#Java学了这么久,项目也做了?基础知识还不巩固?快来关注我的这篇系列博客——Java基础复习巩固吧# 目录 引言 一、JDK8新特性:允许在接口中定义非抽象方法和静态方法。 注意事项 二、JDK9新特性:允许在接口中定义p…

ScriptableObject使用

资料 Scripting/Create modular game architecture in Unity with ScriptableObjects 脚本文档 基础 SO是一个Unity对象,继承UnityEngine.Objec, SO最大的特点是实例文件可共享,有点类似静态数据,同一个实例文件可被多个对象引…

matlab实验:实验六MATLAB 数值计算与符号运算

题目1:(线性方程组数值求解) 1. 用不同的方法求解下面方程:(方程原式参考 P369 实验 10,第 1 题) 第 1 种,左除和求逆函数(inv) 第 2 种 , 用 符 号 运 算 的…

JAVA基础知识4(static、继承)

JAVA基础知识4 static静态成员变量静态成员方法解释注意点 继承父类(基类或超类)子类(派生类)使用继承的示例解释运行结果 成员变量的访问特点成员方法的访问特点构造方法的访问特点 Java项目,包和类之间的联系包的概念…

vue elementui 在table里使用el-switch

<el-table-columnprop"operationStatus"label"状态"header-align"center"align"center"><template slot-scope"scope"><el-switch active-value"ENABLE" inactive-value"DISABLE" v-mod…

【C语言】两个数组比较详解

目录 C语言中两个数组比较详解1. 逐元素比较1.1 示例代码1.2 输出结果1.3 分析 2. 内置函数的使用2.1 示例代码2.2 输出结果2.3 分析 3. 在嵌入式系统中的应用3.1 示例代码3.2 输出结果3.3 分析 4. 拓展技巧4.1 使用指针优化比较4.2 输出结果4.3 分析 5. 表格总结6. 结论7. 结束…

Python写UI自动化--playwright(通过UI文本匹配实现定位)

本篇简单拓展一下元素定位技巧&#xff0c;通过UI界面的文本去实现定位 目录 匹配XPath 匹配文本元素 .count()统计匹配数量 处理匹配文本返回多个元素 1、使用.nth(index)选择特定元素: 2、获取所有匹配的元素并遍历: 3、错误处理: 匹配XPath 比如我们要定位到下图的…

C++笔试强训8

文章目录 一、选择题1-5题6-10题 二、编程题题目一题目二 一、选择题 1-5题 根据下面的定义故选A。 函数重载:在相同作用域中&#xff0c;函数名字相同&#xff0c;参数列表不同的一系列函数称为函数重载参数列表不同具体的体现:参数个数不同参数类型不同类型的次序不同注意:…

单元测试--Junit

Junit是Java的单元测试框架提供了一些注解方便我们进行单元测试 1. 常用注解 常用注解&#xff1a; TestBeforeAll&#xff0c;AfterAllBeforeEach&#xff0c;AfterEach 使用这些注解需要先引入依赖&#xff1a; <dependency><groupId>org.junit.jupiter<…

6 C 语言指针的奥秘:理论与实践详解

目录 1 变量访问机制 1.1 内存地址 1.2 变量的直接访问 1.3 变量的间接访问 2 指针变量及其内存大小 2.1 指针与指针变量 2.2 指针变量的定义格式 2.3 指针变量的内存大小 3 取地址操作符与取值操作符 3.1 取地址操作符 & 3.2 取值操作符 * 3.3 解引用与数据类…

【数据结构】顺序表(杨辉三角、简单的洗牌算法)

&#x1f387;&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了 博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳&#xff0c;欢迎大佬指点&#xff01; 欢迎志同道合的朋友一起加油喔 &#x1f4aa;&#x1f4aa;&#x1f4aa; 谢谢你这么帅…

学习React(描述 UI)

React 是一个用于构建用户界面&#xff08;UI&#xff09;的 JavaScript 库&#xff0c;用户界面由按钮、文本和图像等小单元内容构建而成。React 帮助你把它们组合成可重用、可嵌套的 组件。从 web 端网站到移动端应用&#xff0c;屏幕上的所有内容都可以被分解成组件。在本章…

优化医疗数据管理:Kettle ETL 数据采集方案详解

在现代医疗保健领域&#xff0c;数据的准确性、完整性和及时性对于提高医疗服务质量和患者护理至关重要。为了有效管理和利用医疗数据&#xff0c;Kettle ETL&#xff08;Extract, Transform, Load&#xff09;数据采集方案成为了许多医疗机构的首选工具之一。本文将深入探讨Ke…

【基础算法总结】队列 + 宽搜(BFS)

队列 宽搜BFS 1.N 叉树的层序遍历2.二叉树的锯齿形层序遍历3.二叉树最大宽度4.在每个树行中找最大值 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&#xff0c;我们一起努力吧!&#x1f603;&#…

MySQL作业五

1. 创建表goods&#xff0c;orders 2. 向商品表中插入商品记录 3. 触发器操作 3.1 建立触发器&#xff0c;订单表中增加订单数量后&#xff0c;商品表商品数量同步减少对应的商品订单出数量,并测试 3.2 建立触发器&#xff0c;实现功能:客户取消订单&#xff0c;恢复商品表对应…

java数据结构之排序

前言&#xff1a; 排序在我们日常生活中随处可见&#xff0c;这里将介绍java数据结构里面常见的几种排序。 ps: swap函数的实现&#xff1a; public void swap(int[] arr, int i, int j) {int tmp arr[i];arr[i] arr[j];arr[j] tmp; } 1.直接插入排序 &#xff08;1&a…

类与对象(补充)

初始化列表 1. 之前我们实现构造函数时&#xff0c;初始化成员变量主要使用函数体内赋值&#xff0c;构造函数初始化还有一种方式&#xff0c;就是初始化列表&#xff0c;初始化列表的使用方式是以一个冒号开始&#xff0c;接着是一个以逗号分隔的数据成员列表&#xff0c;每个…

【OpenCV C++20 学习笔记】序列化——XML和YAML文件处理

序列化——XML和YAML文件处理 序列化和反序列化代码实现XML/YAML文件的打开和关闭写入或读取文本和数字写入或读取OpenCV数据写入或读取数组以及map读取和写入自定义数据类型 输出结果 序列化和反序列化 如果希望永久保存某些对象&#xff0c;而不是每次运行程序的时候重新创建…

经典文献阅读之--LIV-GaussMap(实时3D辐射场地图渲染的LiDAR惯性视觉融合算法)

Tip: 如果你在进行深度学习、自动驾驶、模型推理、微调或AI绘画出图等任务&#xff0c;并且需要GPU资源&#xff0c;可以考虑使用UCloud云计算旗下的Compshare的GPU算力云平台。他们提供高性价比的4090 GPU&#xff0c;按时收费每卡2.6元&#xff0c;月卡只需要1.7元每小时&…