10.1 实验内容 通过本实验主要学习以下内容: • 独立看门狗的原理 • 独立看门狗功能介绍 • 实现独立看门狗功能 10.2 实验原理 10.2.1 看门狗的原理 一般来说,搭配MCU的产品都需要有长期运行的需求,特别像一些工业设备,可能要求运行个几年都不关机,但谁也不能保证在这几年里,MCU里面的代码不出任何问题,更何况自然环境中还存在很多电磁干扰、静电等,都可能会导致MCU出现运行异常的情况,比如程序卡死啦,进入错误状态啦等等,这个时候,我们就可以通过一个非常可爱的外设——看门狗,来帮助MCU从异常状态复位,让程序重新开始从头运行。 看门狗实际上是一个定时器,它的工作原理是:将看门狗定时器的计数器设定一个初始值,看门狗开始运行后,定时器中的计数值会在每一个计数器时钟来的时候减1,如果这个计数值减到0,看门狗就会内部给MCU一个复位信号使MCU复位。所以应用程序中必须每隔一段时间要对看门狗的计数值进行一次重载(看门狗计数器恢复到初始值),这样看门狗的计数器就不会减到0了,而当程序出现卡死的情况时,由于不再对看门狗计数器重载,看门狗就会让MCU复位,使MCU从卡死状态恢复出来。这种工作方式是不是就像一条狗,你要每隔一段时间去喂它,否则它就不给你“看门”了,“看门狗”的名字,就是这么来的。 GD32F303片上有两个看门狗外设——独立看门狗(FWDGT)和窗口看门狗(WWDGT),本章我们只讲独立看门狗。 10.2.2 独立看门狗(FWDGT)的时钟 前面讲到,看门狗的计数值在每一个计数器时钟来的时候减1,那么这个时钟是什么呢,我们来看一下GD32F303ZE的时钟树: 从时钟树可以看到,FWDGT的时钟来源于IRC40K,这是GD32F303的内部时钟,典型的频率值是40KHz。但要注意,这个IRC40K不是直接连到FWDGT计数器的,而是需要经过一个预分频器,这个分频器大小通过FWDGT_PSC进行设定。 预分频寄存器(FWDGT_PSC): 如设定PS[2:0]为001b,那么计数器的时钟频率就为40K/8 = 5KHz,即每隔200us计数值减1。 10.2.3 独立看门狗(FWDGT)的重装载 说完时钟,我们来说下FWDGT的计数器和重装载。计数器就是按照前面说的,每来一个计数器时钟,计数器减1,而计数器的初始值,来自于重装载寄存器。 重装载寄存器(FWDGT_RLD): 从“描述”中我们可以看出,向FWDGT_CTL写入0xAAAA(即喂狗,详见用户手册FWDGT_CTL寄存器),重装载寄存器中的数值就会自动加载到FWDGT的计数器中。 重装载寄存器(FWDGT_RLD)是一个12位的计数器,这就意味着重装载最大值为65535,再结合上一节的时钟分频,FWDGT设定的最大/最小超时周期见下表: 注意: 当执行完喂狗reload操作之后,如需要立即进入deepsleep / standby模式时,必须通过软件设置,在reload命令及deepsleep / standby模式命令中间插入(3个以上) IRC40K时钟间隔,否则可能导致喂狗不成功。 |
10.2.4 独立看门狗的使用注意事项 独立看门狗的时钟源来自于IRC40K,这个内部时钟实际上不是非常的准确,所以在设定看门狗重载值和分配器时需要留有一定的余量,防止应用程序由于IRC40K频率偏差而来不及喂狗,导致不必要的MCU复位。 10.3 硬件设计 本实验我们通过红枫派开发板LED0的状态来指示MCU复位情况,用LED1来指示喂狗的情况。 10.4 代码解析 10.4.1 独立看门狗初始化和喂狗函数 在driver_wdgt.c中定义了独立看门狗的配置函数drive_fwdgt_config和喂狗函数Feed_fwdgt: C
void drive_fwdgt_config(uint16_t reload_value, uint8_t prescaler_div)
{
/* 开启内部40K时钟 */
rcu_osci_on(RCU_IRC40K);
/* 等待40K时钟ready */
while(SUCCESS != rcu_osci_stab_wait(RCU_IRC40K)){
}
/*配置看门狗参数*/
fwdgt_config(reload_value,prescaler_div);
/*开启看门狗*/
fwdgt_enable();
}
void Feed_fwdgt(void)
{
/* 重装载计数器 */
fwdgt_counter_reload();
}
10.4.2 main函数实现 以下为main函数代码: C
int main(void)
{
uint8_t i;
delay_init();//delay函数初始化
bsp_led_group_init();//LED初始化
bsp_led_on(&LED0);//点亮LED0
delay_ms(2000); //延时2s
bsp_led_off(&LED0);//熄灭LED0
drive_fwdgt_config(625,FWDGT_PSC_DIV64);//独立看门狗配置
/*闪烁LED1 5次,并每闪烁一次进行喂狗*/
for(i = 0;i<5;i++)
{
delay_ms(500);
bsp_led_toggle(&LED1);
Feed_fwdgt();
}
while (1)
{
}
}
本例程main函数首先进行了延时函数初始化,再初始化LED0和LED1,并将LED0点亮2s钟后熄灭,然后配置独立看门狗时钟预分频为64分频,重载值为1000,即超时时间为625/(40K/64) = 1s,再每500ms翻转一次LED1,同时进行喂狗,最后进入while(1)循环。 10.5 实验结果 红枫派开发板上电后,LED0灯亮,2s钟后熄灭,随后LED1闪烁5次,再经过一段时间后LED1灯灭,LED0复亮,周而复始。
本教程由GD32 MCU方案商聚沃科技原创发布,了解更多GD32 MCU教程,关注聚沃科技官网,GD32MCU技术交流群:859440462
|