STM32F4+RT-Thread IWDG 看门狗 开发实战:从驱动编写到“喂狗、超时复位”指南
目录
- 一、工程环境搭建
- 二、程序编写
- 三、实验与分析
一、工程环境搭建
- 创建一个新工程
- 打开CubeMX 进行工程配置
- 打开IWDG看门狗
- 时钟选择外部晶振
- 配置下载调试口
- 打开串口一
- 配置时钟线
- 选择工具链,我这里用的是MDK-ARM
- 生成.c和.h文件
- 生成代码
- 打开WDT设备驱动程序
- 在构建配置里增加Src/iwdg.c,不然咱在Src目录下看不到该.c文件
- 重新生成一下代码
- 现在就能看到iwdg.c文件了
- 新建system_deal文件夹,再在该文件夹下新建system_deal.c和system_deal.h文件
- 把这个宏定义改一下,改成小写,我发现rtthread5.1.0版本有这个问题,我之前用的是4.1.1版本没这个问题,更新后把宏定义改成小写了不知道为什么,这里我们需要自己手动改一下。
- 改成小写后,我们编译一下,编译通过,环境配置到此为止(那个警告也是更新版本后出现的,暂时不用管)
二、程序编写
- main.c文件主函数里写如下代码
/** Copyright (c) 2006-2025, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2025-09-25 RT-Thread first version*/
#include "system_deal.h"int main(void)
{SystemStartInit();return RT_EOK;
}
2. 在system_deal.文件里写入如下代码
/** Copyright (c) 2006-2021, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2025-09-25 Administrator the first version*/#include "system_deal.h"rt_uint32_t timeout = 10; /* 溢出时间,单位:秒 */
SysDev_t s_tSysDev;/*********************************************************************************************************** Function name: SysDealInit** Descriptions: Sys Deal Init** input parameters: NONE** output parameters: NONE** Returned value: pHmiDev_t*********************************************************************************************************/
static pSysDev_t SysDealInit(void)
{rt_err_t ret = RT_EOK;pSysDev_t psys = (pSysDev_t)&s_tSysDev;rt_memset((uint8_t*)&psys->WdgDev, 0, sizeof(SysDev_t));// set pinrt_pin_mode(SYS_LED, PIN_MODE_OUTPUT);rt_pin_write(SYS_LED, PIN_HIGH); //用来给板子闪灯,观察板子是否正常跑起psys->WdgDev = rt_device_find(WDT_DEVICE_NAME);if (!psys->WdgDev){rt_kprintf("wdt find failed!\n");}rt_device_init(psys->WdgDev);/* 设置看门狗溢出时间 */ret = rt_device_control(psys->WdgDev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout);if (ret != RT_EOK){rt_kprintf("set %s timeout failed!\n", WDT_DEVICE_NAME);}ret = rt_device_control(psys->WdgDev, RT_DEVICE_CTRL_WDT_START, RT_NULL);if (ret != RT_EOK){rt_kprintf("wdt conrtol failed!\n");}return psys;
}/*********************************************************************************************************** Function name: SystemLedRun** Descriptions: System Led Run** input parameters: NONE** output parameters: NONE** Returned value: NONE*********************************************************************************************************/
static void SystemLedRun(void)
{static uint8_t l_ucmode = 0;if (l_ucmode == 0){rt_pin_write(SYS_LED, PIN_HIGH);l_ucmode = 1;}else if (l_ucmode == 1){rt_pin_write(SYS_LED, PIN_LOW);l_ucmode = 0;}
}/*********************************************************************************************************** Function name: SystemFeedDog** Descriptions: System Feed Dog** input parameters: pSysDev_t** output parameters: NONE** Returned value: NONE*********************************************************************************************************/
static void SystemFeedDog(pSysDev_t psys)
{rt_err_t ret = RT_EOK;ret = rt_device_control(psys->WdgDev, RT_DEVICE_CTRL_WDT_KEEPALIVE, NULL);if (ret != RT_EOK){rt_kprintf("feed the dog error!\n ");}
}/*********************************************************************************************************** Function name: SysDevCheck** Descriptions: Sys Dev Check** input parameters: pSysDev_t** output parameters: NONE** Returned value: NONE*********************************************************************************************************/
void SysDevCheck(pSysDev_t psys)
{if ((rt_tick_get() - psys->tSysDevMsg.SysFlushCyc) >= SYS_TICK_TIME){psys->tSysDevMsg.SysFlushCyc = rt_tick_get();SystemLedRun();//SystemFeedDog(psys);rt_kprintf("time:%ds\r\n",rt_tick_get()/1000);}
}/*********************************************************************************************************** Function name: SysDeal_thread** Descriptions: SysDeal thread** input parameters: parameter** output parameters: NONE** Returned value: NONE*********************************************************************************************************/
static void SysDeal_thread(void* parameter)
{pSysDev_t l_ptsys = SysDealInit();while(1){SysDevCheck(l_ptsys);rt_thread_mdelay(10);}
}/*********************************************************************************************************** Function name: SystemDealTaskInit** Descriptions: System Task Init** input parameters: NONE** output parameters: NONE** Returned value: NONE*********************************************************************************************************/
void SystemDealTaskInit(void)
{rt_thread_t SysDeal_tid;SysDeal_tid = rt_thread_create("sys_ctl", SysDeal_thread, RT_NULL, SYS_THREAD_STACK, SYS_THREAD_PRO, SYS_THREAD_TICK);if (SysDeal_tid != RT_NULL){rt_thread_startup(SysDeal_tid);}else{
#if DEBUG_LOG_ENABLErt_kprintf("/--> SysDeal create failed!\n");
#endif}
}/*********************************************************************************************************** Function name: SystemTaskInit** Descriptions: System Task Init** input parameters: NONE** output parameters: NONE** Returned value: NONE*********************************************************************************************************/
static void SystemTaskInit(void)
{SystemDealTaskInit();
}/*********************************************************************************************************** Function name: SystemStartInit** Descriptions: System Start Init** input parameters: NONE** output parameters: NONE** Returned value: NONE*********************************************************************************************************/
void SystemStartInit(void)
{SystemTaskInit();
}
3. 在system_deal.h文件下写入如下代码
/** Copyright (c) 2006-2021, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2025-09-25 Administrator the first version*/
#ifndef APPLICATIONS_SYSTEM_DEAL_SYSTEM_DEAL_H_
#define APPLICATIONS_SYSTEM_DEAL_SYSTEM_DEAL_H_
#include <rtdevice.h>
#include <rtthread.h>
#include "board.h"
#include "stdio.h"/* thread information */
#define SYS_THREAD_STACK 1024
#define SYS_THREAD_PRO 15
#define SYS_THREAD_TICK 10/* system io */
#define SYS_LED GET_PIN(G, 13)/* system wdt */
#define WDT_DEVICE_NAME "wdt"/* system info */
#define SYS_TICK_TIME 1 * 1000/* SysDevMsg */
typedef struct
{uint32_t SysFlushCyc;} SysDevMsg_t;typedef struct
{rt_device_t WdgDev;SysDevMsg_t tSysDevMsg;} SysDev_t, *pSysDev_t;#endif /* APPLICATIONS_SYSTEM_DEAL_SYSTEM_DEAL_H_ */
4. 添加system_deal.h文件路径
5. 编译一下,编译通过
三、实验与分析
- 将程序下进板子,打开串口,可以看到每秒都有打印
- 打印的逻辑在这,1s进一次,打印当前系统时间
- 这个是“喂狗”的函数,我当前是把它注释掉了,也就是说超过一定时间后,系统就会复位
- 这是喂狗函数内部实现。
- 可以看到运行到14s的时候,系统进行了重启,那这个14s是在哪里定的呢?
- 在这个位置,设立了超时时间,如果在14s内没有喂狗,则再超过14s时,系统则会复位
- 我们现在把喂狗的注释打开,验证一下系统是不是就能超过14s的跑下去了
- 可以看到,如果按时喂狗,系统则能正常运行
- 如果我在初始化的时候,不去设置超时时间,那系统默认的看门狗超时时间是多少呢?我们来试一下
- 依旧把喂狗函数注释掉,我们看一下,系统会在多少秒进行复位
- 可以看到系统在33s的时候进行了复位,那这个33s是在哪里确定的呢?
- 在这个位置进行的默认配置,对看门狗的时钟进行了256的分频,然后重装载值是4095,我们来算一下是不是33s
- 首先看门狗的时钟是32KHZ
步骤 1:计算分频后的时钟周期(每个计数的时间)
分频后的时钟频率 = 输入时钟频率 / 分频系数f_div = 32000Hz / 256 = 125Hz
每个计数的时间(即分频后的周期)= 1 / 分频后频率T_div = 1 / 125Hz = 0.008 秒 = 8 毫秒
步骤 2:计算总计数次数
计数器从4095递减到0,总计数次数 = 4095 + 1 = 4096 次
步骤 3:计算总复位时间
总复位时间 = 总计数次数 × 每个计数的时间T_reset = 4096 × 0.008 秒 = 32.768 秒
- 因此是符合预期的,但是我们在使用时还是要记得设置超时时间,这样对程序的把控会更好一些