Arduino 入门学习笔记(九):看门狗实验

Arduino 入门学习笔记(九):看门狗实验

开发板:正点原子ESP32S3
例程源码在文章顶部可免费下载

1. 看门狗简介

MCU 可能工作在一些复杂环境,可能受到某些电磁干扰出现程序跑飞,导致死循环无法继续执行工作,看门狗的作用就是为了避免这种情况。看门狗的本质也是一个定时器,在程序启动后,需要在一定的时间内再给它一个信号,俗称“喂狗”。 如果没有按时“喂狗”,说明系统
或软件出现了不可预知的问题(比如软件卡在某个循环或逾期事件中), 这时看门狗就向系统发送个复位信号,使整个系统重启,重新进入正常的工作状态。 看门狗有助于检测、处理系统或软件的错误行为。
ESP32-S3 中有3个数字看门狗定时器、 1 个模拟看门狗定时器和一个 XTAL32K 看门狗定时器,他们在各自有特定条件运行。 本实验主要用是通用定时器模拟看门狗功能。本实验用到的函数跟上一个笔记定时器中断实验用到的函数是一致的。

2. 硬件设计

2.1 例程功能

程序启动后, 配置定时器的定时时间为 1.2 秒,定时到来时执行中断回调函数中打印操作以及软件复位操作。 主循环中每隔 1 秒给进行喂狗,若按下按键会延时 0.5 秒,会导致无法在1.2 秒内进行喂狗,导致进入中断回调函数中进行软件复位。

2.2 硬件资源

1)独立按键:BOOT-IO0
2) USART0:U0TXD-IO43 U0RXD-IO44
3) Timer1

2.3 原理图

本实验使用的定时器为 ESP32-S3 的片上资源,因此并没有相应的连接原理图。

3. 软件设计

3.1 程序流程图

下面看看本实验的程序流程图:
在这里插入图片描述

3.2 程序解析

watchdog 驱动代码
这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。 WATCHDOG 驱动源码包括两个文件: watchdog.cpp 和 watchdog.h。
下面我们先解析 watchdog.h 的程序。 对看门狗功能的定时器做了相关定义。

#define WDG_TIMx 1 /* 模拟看门狗用到的定时器 */
#define WDG_ISR tim1_ISR /* 定时器中断服务函数 */

我们选择使用通用定时器 1 作为模拟看门狗的定时器,当然你也可以通过改变 WDG_TIMx的值选择别的定时器作为看门狗功能。 WDG_ISR 宏是定时器 1 的中断回调函数,采用该宏移植性更加强。
下面我们再解析 watchdog.cpp 的程序,这里有两个函数 wdg_init 和 TIMX_ISR,其定义如下:
ESP32新版本Timer定时器库进行了修改,如果使用新版本,timx_int_init函数也需要进行相应修改,具体说明请参考博博文

hw_timer_t *wdg_timer = NULL;
/**
* @brief 初始化看门狗
* @note
* 定时器的时钟来自 APB,而 APB 为 80M
* 所以定时器时钟 = (80/psc)Mhz, 单位时间为 1 / (80 / psc) = x us
* 定时器溢出时间计算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us
* Ft=定时器工作频率,单位:Mhz
*
* @param arr: 自动重装值
* @param psc: 时钟预分频数
* @retval 无
*/
void wdg_init(uint32_t arr, uint16_t psc)
{
	wdg_timer = timerBegin(WDG_TIMx, psc, true); /* 初始化定时器 1 */
	timerAlarmWrite(wdg_timer, arr, true); /* 设置中断时间 */
	timerAttachInterrupt(wdg_timer, &WDG_ISR, true); /* 配置定时器中断回调函数 */
	timerAlarmEnable(wdg_timer); /* 使能定时器中断 */
	
	/* 新版本使用以下初始化代码 v3.2.0*/
    //timer = timerBegin(10000);
    //timerAttachInterrupt(timer, &TIMx_ISR);
    //timerAlarm(timer, 10000, true, 0);
}
/**
* @brief 看门狗定时器中断回调函数
* @param 无
* @retval 无
*/
void WDG_ISR(void)
{
	ets_printf("reboot\n");
	esp_restart();
}

wdg_init 函数是初始化定时器 1,首先调用 timerBegin 函数初始化一个定时器对象并采用向上计数方式,然后调用 timerAlarmWrite 函数配置中断时间并设置自动加载,后面再调用timerAttachInterrupt 函数设置定时器边沿触发中断,最后调用 timerAlarmEnable 函数使能开启定时器。
注意:定时器的定时时间是由 wdg_init 函数的参数决定,这里我们还定义了一个全局的hw_timer_t 类型的结构体指针 wdg_timer。
WDG_ISR函数就是定时器1中断回调函数。函数比较简单, 调用ets_printf函数打印“reboot”,后面就是调用 esp_restart 函数执行软件复位。
这里需要注意:需要在 watchdog.h 中添加 esp_system 头文件支持。
06_watch_dog.ino 代码
在 06_watch_dog.ino 里面编写如下代码:

#include "uart.h"
#include "key.h"
#include "watchdog.h"
#define wdg_timeout 1200 /* 看门狗定时时间,1200ms */
/**
* @brief 当程序开始执行时,将调用 setup()函数,通常用来初始化变量、函数等
* @param 无
* @retval 无
*/
void setup()
{
key_init(); /* KEY 初始化 */
uart_init(0, 115200); /* 串口 0 初始化 */
Serial.println("running setup"); /* 打印标志性信息 方便查看系统开始 */
wdg_init(wdg_timeout * 1000, 80); /* 初始化看门狗,80 分频,定时时间 1.2 秒 */
}
/**
* @brief 循环函数,通常放程序的主体或者需要不断刷新的语句
* @param 无
* @retval 无
*/
void loop()
{
Serial.println("running main loop"); /* 打印标志性信息 方便查看系统开始 */
timerWrite(wdg_timer, 0); /* 复位定时器(喂狗) */long looptime = millis();
/* 通过 millis 函数获取开发板开始运行当前程序以来经过的毫秒数 */
while (!KEY) /* 按下按键会延时 500ms,最终会导致 looptime 时间变为 1.5 秒,还没有来得及喂
狗,就进入到定时器中断回调函数中复位 */
{
Serial.println("key pressed, delay_500ms");
delay(500);
}
delay(1000);
looptime = millis() - looptime; /* 监控上过程运行时间 */
Serial.print("loop time is = "); /* 打印上过程运行时间 */
Serial.println(looptime);
}

在 setup 函数中, 调用 key_init 完成按键初始化,调用 uart_init 函数完成串口 0 的初始化,然后调用 wdg_init 函数初始化定时器 1,这里设置的定时的时间为 1.2 秒,通过 wdg_timeout 宏决定。
在 loop 函数中,一开始串口打印时间执行的标识,然后调用 timerWrite 函数设置定时器的计数器值为 0。该操作相当于喂狗操作,这时候,定时器就会从 0 开始计数,向 1200000 递增计数,当计数到 1199999 就会进入到我们编写好的 WDG_ISR 中执行操作。 但是程序正常执行下(把按键检测的程序去掉),这时候会调用 delay 函数延时 1 秒,这种执行下,定时器进入不到中断的。所以要使得定时器进入到中断,就需要按下按键,这时候就会超时,没有在 1.2 秒内喂狗,导致进入到中断回调函数中进行软件复位操作。以上就是简单的例子演示模拟看门狗,无法及时喂狗,就会导致程序复位。很多时候,编写程序,会发现程序一直重启,不能正常运行,很大可能就是系统跑飞,导致看门狗无法及时喂养。
上面程序中用到函数 millis,该函数的作用是获得程序运行的时间(以毫秒为单位)。

4. 下载验证

下载代码完成后, ESP32-S3 开发板串口输出信息,执行 loop 代码的时间。当按键按下时,会进行复位。无按键按下时,会隔 1 秒打印 loop 代码执行时间。有无按键按下时程序执行情况如下图所示:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值