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框图的①所示, 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的时候才可以更新重装载寄存器/预分频寄存器。
注意:
如果在选项字节中打开了“硬件看门狗定时器”功能,那么在上电的时候看门狗定时器就被自动打开。为了避免系统复位,软件应该在计数器达到0x000之前重装载计数器;
如果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 || GD32E230 rcu_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 || GD32E10X gpio_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 || GD32E230 gpio_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方案商聚沃科技原创发布,了解更多GD32 MCU教程,关注聚沃科技官网
-
单片机
+关注
关注
6078文章
45581浏览量
673737 -
mcu
+关注
关注
147文章
19134浏览量
404057 -
看门狗
+关注
关注
10文章
611浏览量
73200 -
GD32
+关注
关注
7文章
434浏览量
27627
发布评论请先 登录
GD32 MCU 入门教程】GD32 MCU 常见外设介绍(12)FMC 模块介绍
GD32 MCU移植
《GD32 MCU原理及固件库开发指南》+读后感
兆易创新GD32 MCU选型手册,适用于GD32全系列MCU
【GD32 MCU 入门教程】一、GD32 MCU 开发环境搭建(1)使用Keil开发GD32
【GD32 MCU 入门教程】一、GD32 MCU 开发环境搭建(2)使用 IAR 开发 GD32
【GD32 MCU 入门教程】一、GD32 MCU 开发环境搭建(3)使用 Embedded Builder 开发 GD32
【GD32 MCU 入门教程】二、GD32 MCU 烧录说明(1)ISP 烧录
【GD32 MCU 入门教程】GD32 MCU 常见外设介绍(14)RTC 模块介绍
【GD32 MCU入门教程】GD32 MCU GPIO 结构与使用注意事项
【GD32 MCU 入门教程】GD32 MCU 常见外设介绍(9)FWDG 模块介绍
评论