当前位置: 首页 > news >正文

9.【NXP 号令者RT1052】开发——实战-看门狗

9.【NXP 号令者RT1052】开发——实战-看门狗

这一章,我们将向大家介绍如何使用 RT1052 的普通看门狗(WDOG1)。RT1052 内部自带了 3 个看门狗:普通看门狗(WDOG1 和 WDOG2)和 RT 看门狗(WDOG3)。这一章我们只介绍普通看门狗,RT 看门狗将在下一章介绍。在本章中,我们将利用看门狗的中断功能来喂狗。

9.1 RT1052 看门狗简介

看门狗可以保证系统的正常运行,当系统运行出现异常/错误时,看门狗可以及复位系统,以免带来不能挽回的后果。
RT1052 的看门狗时钟一般由外部 32.768Khz 低速时钟(外部低速晶振)驱动,即使主时钟发生故障,它也仍然有效。注意:当外部 32.768Khz 晶振失效时,芯片将自动切换到内部 RC 时钟,保障看门狗的正常运行。内部 RC 时钟频率一般为:10Khz~45Khz。RT1052 看门狗框图如下:
在这里插入图片描述
看门狗的计数时钟来自低速参考时钟(Low Frequency Reference Clock 1),通常为外部 32.768 kHz 晶振或内部 10~45 kHz RC 振荡器,一般使用外部 32.768 kHz 晶振。看门狗有三个输出信号:wdog_rst(用于复位 MCU)、Interrupt(用于产生中断)、WDOG-1(输出 WDOG_B 信号)。其中中断信号由内部中断计数器产生,可用于在复位前触发中断喂狗。

RT1052 内部包含两个普通看门狗:WDOG1 和 WDOG2。两者功能相似,但 WDOG1 溢出时会产生复位信号,直接复位 MCU;WDOG2 溢出则触发 SNVS 中断,用于错误报告。本章以 WDOG1 为例。

看门狗控制寄存器(WCR)用于控制看门狗的工作,常用位功能如下:

  • WT[7:0]:设置溢出时间,范围 0~127,对应 0.5~128 秒。喂狗或使能后该值加载到计数器并递减至 0,产生溢出并复位 MCU。喂狗操作会重新加载该值。
  • WDA/WDT:控制 WDOG_B 信号输出。一般保持默认(WDA=1,WDT=0)。
  • SRS:输出软复位信号,通常设置为 1。
  • WDE:看门狗使能位,必须设置为 1 才能启用看门狗。注意该位为一次性设置,硬件复位前无法修改;WDT 位同样如此。

在这里插入图片描述

接下来,我们介绍看门狗服务(喂狗)寄存器(WSR),该寄存器用于实现喂狗操作

在这里插入图片描述
我们依次往该寄存器(WSR)写入两个值:0X5555、0XAAAA,即可实现喂狗操作。注意,这两个值必须按顺序写入!当写完这两个值以后,看门狗计数器值就会自动从 WT[7:0]重新加载,从而实现喂狗。
接下来,我们介绍看门狗中断控制寄存器(WICR),该寄存器用于控制看门狗的中断。
在这里插入图片描述
WIE 位,用于设置是否使能看门狗中断。本章我们将使用中断来喂狗,所以需要设置该位为 1。
WTIS 位,用于表示看门狗中断是否发生。该位为写 1 清零。
WICT[7:0]位,用于设置看门狗中断计数器溢出时间,表示中断溢出到看门狗溢出之间的时间,即提前看门狗溢出多少时间进入中断,其设置范围为 0~255,表示 0~127.5 秒。例如,设置WICT[7:0]=0X01,表示看门狗中断产生后,0.5 秒就会产生看门狗溢出,即提前 0.5 秒进入中断;如设置 WICT[7:0]=0X06,表示看门狗中断产生后,3 秒就会产看门狗溢出,即提前 3 秒进入中断。注意:WICT[7:0]设置的提前时间,必须小于 WT[7:0]设置的溢出时间!!

最后,我们看看门狗中的杂项控制寄存器(WMCR)。
在这里插入图片描述
该寄存器只有最低位(PDE)有效,其他都为保留位。当设置 PDE=0 时,禁止 WDOG 掉电计数器工作。当设置 PDE=1 时,使能 WDOG 掉电计数器工作。为了让 WDOG 正常工作,我们设置改位为 0 即可。
只要对以上几个寄存器进行相应的设置,我们就可以启动 RT1052 的看门狗。

看门狗相关的库函数在 fsl_wdog.c 和 fsl_wdog.h 这两个文件中。我们以 WDOG1 为例,看看库函数的看门狗配置步骤

1. 使能 WDOG1 时钟

  • 要正常设置 WDOG1 寄存器,必须先使能其时钟。

  • 使用函数:

    c

    CLOCK_EnableClock(kCLOCK_Wdog2);
    
  • 注意:WDOG_Init 会自动调用此函数打开时钟,因此一般无需手动调用。

2. 初始化 WDOG1

  • 使用 FSL 库函数:

    c

    void WDOG_Init(WDOG_Type *base, const wdog_config_t *config);
    
  • 参数说明:

    • base:指定看门狗(WDOG1 或 WDOG2)。
    • config:看门狗配置结构体指针,类型为 wdog_config_t

c

typedef struct _wdog_config
{bool enableWdog;              // 使能看门狗wdog_work_mode_t workMode;    // 工作模式bool enableInterrupt;         // 使能中断uint16_t timeoutValue;        // 超时时间uint16_t interruptTimeValue;  // 超时前几秒产生中断bool softwareResetExtension;  // 软件复位扩展bool enablePowerDown;         // Power Down 模式bool softwareAssertion;       bool softwareResetSignal;     
} wdog_config_t;
  • 关键参数
    • timeoutValue:喂狗超时时间,公式:

超时时间=(timeoutValue+1)×0.5 秒超时时间 = (timeoutValue + 1) \times 0.5 \ \text{秒}

范围:0.5 ~ 128 秒。

  • interruptTimeValue:提前中断时间,公式:

中断时间=interruptTimeValue×0.5 秒中断时间 = interruptTimeValue \times 0.5 \ \text{秒}

范围:0.5 ~ 127.5 秒。

  • 使用示例:

    c

    wdog_config_t wdog1_config;
    WDOG_GetDefaultConfig(&wdog1_config);   // 默认配置wdog1_config.workMode.enableWait = false;   // 关闭等待模式
    wdog1_config.workMode.enableStop = false;   // 关闭 stop 模式
    wdog1_config.workMode.enableDebug = false;  // 关闭 debug 模式
    wdog1_config.timeoutValue = wdgtimeout;     // 设置超时值
    wdog1_config.interruptTimeValue = inttimeout; // 设置提前中断时间
    wdog1_config.enableInterrupt = true;        // 使能中断
    wdog1_config.enableWdog = true;             // 使能看门狗WDOG_Init(WDOG1, &wdog1_config);            // 初始化 WDOG1
    

3. 喂狗操作

  • 使用函数:

    c

    void WDOG_Refresh(WDOG_Type *base);
    
  • 实际上是向寄存器 WSR 写入特定序列:0xAAAA0x5555

4. 开启 WDOG 中断并设置优先级

  • 配置中断优先级并使能:

    c

    RT1052_NVIC_SetPriority(WDOG1_IRQn, 4, 0); // 抢占优先级 4,子优先级 0
    EnableIRQ(WDOG1_IRQn);                     // 使能 WDOG1 中断
    

5. 编写中断服务函数

  • 在 ISR 中完成喂狗操作:
    • 调用 WDOG_Refresh(WDOG1) 写入序列(0x5555、0xAAAA)。
    • 使用 WDOG_ClearInterruptStatus(WDOG1) 清除中断标志位 WTIS。

实验现象

  • DS0:指示 MCU 是否被复位,若复位则点亮 300ms。

  • DS1:指示中断喂狗,每次中断喂狗翻转一次。

9.2 硬件设计

  1. 指示灯 DS0 和 DS1
  2. 看门狗 1(WDOG1)
    其中指示灯前面介绍过了,看门狗 1(WDOG1)属于 RT1052 的内部资源,只需要软件设
    置好即可正常工作。我们通过 DS0 和 DS1 来指示 RT1052 的复位情况和看门狗 1 的喂狗情况。

9.3 软件设计

软件设计我们依旧是在前面的代码基础上往上加。在 HARDWARE 文件夹下面新建一个 WDOG 的文件夹,用来保存与看门狗相关的代码。然后打开工程,新建 wdog.cwdog.h 两个文件,并保存在WDOG 文件夹下,并将 WDOG 文件夹加入头文件包含路径**(注意:3 个目标工程需要添加 3 次!)**
wdog.c

#include "wdog.h"
#include "lpuart.h"
#include "led.h"wdog_config_t wdog1_config; //WDOG配置结构体//初始化WDOG1
//wdgtimeout:看门狗超时时间,实际时间为(wdgtimeout+1)*0.5s
//			 比如如果要设置超时时间为2s的话wdgtimeout=2/0.5-1=3
//inttimeout:在看门狗超时发生前几秒产生中断?实际时间为inttimeout*0.5s
void WDOG1_Init(u8 wdgtimeout, u8 inttimeout)
{//WDOG_Init()函数里面会使能看门狗时钟,这里写出来是提醒大家使用看门狗//的时候看门狗时钟是要使能的。CLOCK_EnableClock(kCLOCK_Wdog1); 			//使能看门狗时钟WDOG_GetDefaultConfig(&wdog1_config);		//先将WDOG1配置为默认值wdog1_config.workMode.enableWait=false;		//等待模式关闭wdog1_config.workMode.enableStop=false;		//stop模式关闭wdogwdog1_config.workMode.enableDebug=false;	//debug模式关闭wdog	wdog1_config.timeoutValue=wdgtimeout;		//设置超时值,周期为(wdgtimeout+1)*0.5wdog1_config.interruptTimeValue=inttimeout;	//设置wdog超时前几秒产生中断? inttimeout*0.5wdog1_config.enableInterrupt=true;			//使能wdog中断wdog1_config.enableWdog=true;				//使能wdogWDOG_Init(WDOG1,&wdog1_config);				//初始化看门狗//配置WDOG中断RT1052_NVIC_SetPriority(WDOG1_IRQn,4,0);	//抢占优先级4,子优先级0EnableIRQ(WDOG1_IRQn);						//使能WDOG1中断
}//喂狗
void WDOG1_Feed(void)
{  WDOG_Refresh(WDOG1);//重装载	
}//看门狗中断服务函数
void WDOG1_IRQHandler(void)
{if(WDOG_GetStatusFlags(WDOG1) & kWDOG_InterruptFlag)	//超时要发生{WDOG1_Feed();	//喂狗LED1_Toggle;}WDOG_ClearInterruptStatus(WDOG1,kWDOG_InterruptFlag);	//清除中断标志__DSB();				//数据同步屏蔽指令
}

该代码就 3 个函数:WDOG1_Init 函数用于初始化 WDOG1 看门狗,根据我们前面介绍的步骤,设置看门狗的溢出时间,以及喂狗中断溢出时间,打开相应的中断,设置中断优先级;WDOG1_Feed 函数用于喂狗操作,此函数就是对库函数 WDOG_Refresh 的简单封装;
WDOG1_IRQHandler 函数是看门狗 1(WDOG1)的中断服务函数,当中断发生时,我们可以在该函数进行喂狗,并清零中断标记,最后对 LED1(DS1)取反,来监测中断服务函数的执行状况。
保存 wdog.c,然后把该文件加入到 HARDWARE 组下。

wdog.h

#ifndef _WDOG_H
#define _WDOG_H
#include "sys.h"void WDOG1_Init(u8 wdgtimeout, u8 inttimeout);
void WDOG1_Feed(void);
#endif

保存两个代码。
在这里插入图片描述
然后更新main.c

#include "sys.h"
#include "lpuart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "wdog.h"int main(void)
{u8 key=0;u8 led0sta=1,led1sta=1;     //LED0,LED1的当前状态u8 len;					//接收数据长度u16 times=0;            //延时计数器MPU_Memory_Protection();    //初始化MPURT1052_Clock_Init();	    //配置系统时钟DELAY_Init(600);		    //延时函数初始化LPUART1_Init(115200);       //初始化串口1RT1052_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);//优先级分组4LED_Init();				    //初始化LED
#ifdef KEY_DEBUGKEY_Init();                 //初始化KEY
#endif
#ifdef LPUART_DEBUGLED0(0);					//先点亮红灯 
#endif
#ifdef EXTIX_DEBUGEXTIX_Init();			    //初始化外部中断
#endifWDOG1_Init(3,2);		    //初始化看门狗1,2秒溢出,提前1秒进入中断,方便喂狗LED0(0);               	    //先点亮LED灯delay_ms(300);				//延时300ms再初始化看门狗,LED0的变化"可见"while(1){LED0(1);				//关闭DS0,如不复位,DS0将一直处于关闭状态.delay_ms(100); 
#ifdef EXTIX_DEBUGprintf("Int example driver!\r\n");delay_ms(1000);
#endif
#ifdef KEY_DEBUGkey=KEY_Scan(0); 		    //得到键值if(key){	switch(key){				 case WKUP_PRES:	//控制LED0,LED1互斥点亮led1sta=!led1sta;led0sta=!led1sta;break;case KEY2_PRES:	//控制LED0翻转led0sta=!led0sta;break;case KEY1_PRES:	//控制LED1翻转	 led1sta=!led1sta;break;case KEY0_PRES:	//同时控制LED0,LED1翻转 led0sta=!led0sta;led1sta=!led1sta;break;}LED0(led0sta);		//控制LED0状态LED1(led1sta);		//控制LED1状态}else delay_ms(10);
#endif // KEY_DEBUG
#ifdef LPUART_DEBUGif(LPUART_RX_STA&0x8000){					   len=LPUART_RX_STA&0x3fff;//得到此次接收到的数据长度printf("\r\n发送的消息为:\r\n");LPUART_WriteBlocking(LPUART1,LPUART_RX_BUF,len);//发送接收到的数据printf("\r\n\r\n");//插入换行LPUART_RX_STA=0;}else{times++;if(times%5000==0){printf("\r\nALIENTEK RT1052开发板 串口实验\r\n");}if(times%200==0)printf("请输入数据,以回车键结束\r\n");  if(times%30==0)LED0_Toggle;//闪烁LED,提示系统正在运行.delay_ms(10);   }
#endif // LPUART_DEBUG}
}

该函数通过 LED0(DS0)来指示是否正在初始化。而 LED1(DS1)用来指示是否发生了中断。我们先让 LED0 亮 300ms,然后关闭以用于判断是否有复位发生了。在初始化 WDOG1(2 秒溢出,提前 1 秒中断)之后,我们回到死循环,关闭 LED0,并等待看门狗中断的触发/复位。

编译,报错???
哦哦哦哦哦!!!!!忘记导入看门狗的FSL库了。
在Keil MDK FSLLIB里添加对应文件
在这里插入图片描述
编译,OK!没问题,下载代码

可以看到 DS0 亮一下之后熄灭,紧接着 DS1 开始不停的闪烁。每 2 秒亮灭一次,和我们预期的一
致,说明我们的实验是成功的。

总结

看门狗其实以及很形象了,就像一条狗一直叫,饿了就不叫了,但是你喂它吃一口,它就继续叫。我需要它一直叫看门,所以隔一段时间就喂一口。如果太长时间没有喂就饿死了,但是过一会就生了一条新狗接着叫。哈哈哈哈,反正我是这么理解的。
OK!谢谢大家!

http://www.dtcms.com/a/579081.html

相关文章:

  • 重启虚拟机后,静态IP地址通过ip addr无法查看,也就无法实现远程连接 ---- 兜底解决方案
  • 【HarmonyOS NEXT】内存泄漏防护:常见场景与解决方案
  • 制作类网站手机网站域名和pc域名的区别
  • 做视频网站需要流媒体吗国内高清视频素材网站
  • 基于高斯伪谱法的弹道优化方法及轨迹仿真计算
  • 怎么给网站做自适应wordpress.重装
  • 建设网站模块需要哪些google浏览器下载安装
  • 中山半江红网站建设重庆建工集团建设网站
  • 长尾识别BBN方法
  • 如何在Typora中嵌入视频
  • 三轴云台之多维度协同技术
  • 企业如何建公司网站网页模版比较出名的网站
  • 区块链媒体网站建设培训机构网页设计模板
  • 嵌入未来,公式无限
  • DICOM文件厚度信息的作用
  • 皇岗网站建设广东各地最新病例
  • 做网站的人能看到浏览的人的信息吗自驾游网站模板
  • 用七牛做网站公司做网站买服务器多少钱
  • 衡水网站优化推广城乡建设部网站广州市
  • 山东天成建设工程有限公司网站网站建设基础考试
  • 从Python到仓颉:核心项目内容迁移实践
  • 长沙做网站排名最近在线直播免费观看
  • 手机网站推广法中国建筑装修装饰
  • 广州pc网站建设大学生网站开发目的
  • 公司名称变更网站要重新备案网站的flash怎么做
  • wordpress版 影视站网页设计的摘要怎么写
  • 外贸型网站建设公司汕头网站建设托管
  • 武汉大学《AM》:液态金属法合成破纪录铼纳米颗粒!强度67.8 GPa同时实现80%超高塑性
  • 用Python打造智能成绩分析系统:从异常处理到断言验证的全流程实战
  • 想要找个网站做环评公示中国网络运营商排名