本文章基于兆易创新GD32 MCU所提供的2.2.4版本库函数开发
后续项目主要在下面该专栏中发布:
手把手教你嵌入式国产化_不及你的温柔的博客-CSDN博客
感兴趣的点个关注收藏一下吧!
电机驱动开发可以跳转:
手把手教你嵌入式国产化-实战项目-无刷电机驱动(1)-CSDN博客
BMS电源系统开发可以跳转:暂未放链接
向上代码兼容GD32F303RCT6中使用
本项目配套开发板:
基于GD32F103RCT6国产GD32平台,以下教程编写基于该开发板
图片:
原理图以及例程请联系客服获取!
介绍:
GD32系列微控制器集成了独立看门狗(FWDGT)和窗口看门狗(WWDGT)功能,看门狗定时器(WDGT)是一个硬件计时电路,用以提高系统的稳定性和可靠性;他们是提升系统鲁棒性和可靠性的重要组件。
独立看门狗(FWDGT)
工作原理:
时钟源:
GD32F103RCT6的FWDGT使用的是独立的时钟源IRC40K,频率大约为40kHz。不受系统时钟的影响,确保了其独立性和可靠性。当内部向下计数器的计数值达到0的时候,就会发生一个系统复位。
功能:
FWDGT的主要职责是在设定的时间周期内,如果软件没有通过写入喂狗寄存器来重置看门狗计数器,它将自动触发一个系统复位,一般用来避免由于软件问题导致的系统冻结、停止。
配置与使用:
用户需要在初始化阶段设置好预分频系数,决定看门狗的超时时间。一旦配置完成,必须在每个超时周期结束前向FWDGT的喂狗寄存器写入一个特定值来重置计数器,否则就会触发复位。
特点:
1.FWDGT不支持中断机制,其复位动作是不可屏蔽的,适用于需要高度可靠性的系统保护场景。
2.自由运行的12位向下计数器
3.独立时钟源,在主时钟故障时依旧可以工作,包括待机和深度睡眠模式
4.独立看门狗定时器硬件控制位,用来控制是否在上电时自动启动
独立看门狗定时器带有一个8级预分频器和一个12位的向下递减计数器。
窗口看门狗(WWDGT)
工作原理:
时钟源:
窗口看门狗定时器时钟是由APB1时钟预分频而来。窗口看门狗定时器适用于需要精确计时的 场合。功能:
与FWDGT不同,WWDGT要求在预定义的一个时间窗口内完成喂狗操作。如果喂狗太早(窗口开启前)或太晚(错过窗口),都会触发系统复位。
配置与使用:
用户需根据应用需求设置窗口的上下限,以确定合适的喂狗时间范围。在使用过程中,软件需在窗口打开期间喂狗以避免复位。
特点:
1.WWDG可以配置中断,但中断主要用于提示喂狗时间即将到来,而不能阻止复位的发生。它更适合于对程序执行时间有严格限制和监控需求的应用。
2.可编程的7位自由运行向下递减计数器
3.当窗口看门狗使能后,有两种情况会产生复位:
一:当计数值达到0x3F时复位(CNT[6]位被清0)
二:当计数器的值大于窗口寄存器的值时,更新计数器会产生复位
代码演示:
在写一段代码前,我们可以先参考官方提供的例程:
int main(void)
{
/* configure systick */
systick_config();
/* configure LED */
gd_eval_led_init(LED2);
gd_eval_led_init(LED3);
/* configure the Tamper key which is used to reload FWDGT */
gd_eval_key_init(KEY_TAMPER, KEY_MODE_EXTI);
delay_1ms(500);
/* configure FWDGT counter clock: 40KHz(IRC40K) / 64 = 0.625 KHz */
fwdgt_config(2 * 500, FWDGT_PSC_DIV64);
/* after 1.6 seconds to generate a reset */
fwdgt_enable();
/* check if the system has resumed from FWDGT reset */
if(RESET != rcu_flag_get(RCU_FLAG_FWDGTRST)) {
/* turn on LED3 */
gd_eval_led_on(LED3);
/* clear the FWDGT reset flag */
rcu_all_reset_flag_clear();
while(1) {
}
} else {
/* turn on LED2 */
gd_eval_led_on(LED2);
}
while(1) {
}
}
在这里,官方是直接调用看门狗对应的库函数,然后在主函数中完成初始化和喂狗操作,我们在前面几期教程中也已经讲过,为了方便不同项目的移植和维护,我们采样封装的方式,去对每个函数进行封装和接口留出;
独立看门狗初始化
void FWDGT_Init(uint8_t prer,uint16_t rlr)
{
fwdgt_write_enable(); //使能对寄存器的写操作
fwdgt_config(rlr, prer); //设置重装载值和预分频值
fwdgt_counter_reload(); //将FWDGT_RLD寄存器的值重装载FWDGT计数器
fwdgt_enable(); //使能独立看门狗定时器
}
使用例子:
#define reload_number 625
FWDGT_Init(FWDGT_PSC_DIV64,reload_number); //分频数为64,重载值为625,溢出时间为1s
喂狗代码:
可以直接调用GD32库函数中的喂狗操作:
fwdgt_counter_reload(); //喂狗
窗口看门狗初始化
void WWDGT_Init(uint8_t tr,uint8_t wr,uint32_t fprer)
{
rcu_periph_clock_enable(RCU_WWDGT); //使能WWDGT时钟
wwdgt_config(tr, wr, fprer); //设置WWDGT计数器值、窗口值和预分频值 ;
wwdgt_enable(); //使能窗口看门狗定时器
wwdgt_flag_clear(); //清除WWDGT提前唤醒中断标志位状态
wwdgt_interrupt_enable(); //使能窗口看门狗提前唤醒中断
nvic_irq_enable(WWDGT_IRQn, 0, 3); //抢占优先级0,响应优先级为3
}
使用例子
#define count_number 0x8F
#define WWD_number 0x4F
WWDGT_Init(count_number,WWD_number, WWDGT_CFG_PSC_DIV8); //计数器值为8F,窗口值为4F,预分频值为8
提前唤醒中断函数
void WWDGT_IRQHandler(void)
{
wwdgt_counter_update(100); //更新窗口看门狗值
wwdgt_flag_clear(); //清除WWDGT提前唤醒中断标志位状态
/***********************************************/
用户代码编辑区域
/***********************************************/
}
拓展
那么我们通过调用上面不同的功能函数,就能够完成看门狗的初始化和定义了,不知道大家对以前我发过的一篇文章有没有印象:
GD32F103RCT6/GD32F303RCT6-杂项-GD32复位源寄存器(判断复位/重启生成)
哈哈,答案来了,在外面之前这篇文章里面,我们完成了对每次复位以后,对上一次复位来源的分析,那么是不是就意味着,当看门狗发生复位以后,我们能够每次重启读取到呢?
再深一点,是不是就意味着我们每次因为软件故障导致开门狗复位以后,都能在下一次复位后重新读出,告诉用户上一次发生了复位!这将对我们调试和找错误有极大的帮忙!
群号:621154399
有问题欢迎大家加入我们一起交流,这个群是开源性技术交流群。
感兴趣点个关注支持一下吧!