窗口看门狗与编程实验

文章目录[隐藏]

更多交流欢迎关注作者抖音号:81849645041

目标

        了解窗口看门狗的工作原理及其使用场景,通过喂狗事件使窗口看门狗不产生复位。

原理

        STM32有两个看门狗,一个是独立看门狗,一个是窗口看门狗。我们知道独立看门狗的工作原理就是一个递减计数器在 LSI时钟的驱动下不断的往下递减计数,当减到 0之前如果没有刷新递减计数器的值(即俗称的喂狗)的话,产生复位。窗口看门狗跟独立看门狗一样,也是一个递减计数器不断的往下递减计数,当减到一个固定值 0X40时还不喂狗的话,产生复位,这个值叫窗口的下限,是固定的值,不能改变。这个是跟独立看门狗类似的地方,不同的地方是窗口看门狗的计数器的值在减到某一个数之前喂狗的话也会产生复位,这个值叫窗口的上限,上限值由用户独立设置。窗口看门狗计数器的值必须在上窗口和下窗口之间才可以喂狗,这就是窗口看门狗中窗口两个字的含义。独立看门狗和窗口看门狗的区别如下:

 

        RLR 是重装载寄存器,用来设置独立看门狗的计数器的值。TR 是窗口看门狗的计数器的值,由用户独立设置,WR 是窗口看门狗的上窗口值,由用户独立设置。

        窗口看门狗功能框图如下:

  • 窗口看门狗时钟:窗口看门狗时钟来自PCLK1,PCLK1最大是42M,由RCC时钟控制器开启。
  • 计数器时钟:计数器时钟由 CK计时器时钟经过预分频器分频得到,分频系数由配置寄存器 CFR 的位 8:7 WDGTB[1:0]配置,可以是[0,1,2,3],其中 CK计时器时钟=PCLK1/4096,除以 4096是手册规定的。所以计数器的时钟 CNT_CK=PCLK1/4096/(2^WDGTB),这就可以算出计数器减一个数的时间 T= 1/CNT_CK = Tpclk1 * 4096 * (2^WDGTB)。
  • 计数器:窗口看门狗的计数器是一个递减计数器,共有 7 位,其值存在控制寄存器 CR 的位 6:0,即 T[6:0],当 7 个位全部为 1时是 0x7F,这个是最大值,当递减到 T6 位变成 0时,即从0x40 变为 0x3F时候,会产生看门狗复位。这个值 0x40 是看门狗能够递减到的最小值,所以计数器的值只能是:0x40~0x7F之间,实际上用来计数的是 T[5:0]。当递减计数器递减到 0x40 的时候,还不会马上产生复位,如果使能了提前唤醒中断:CFR 位 9 EWI 置 1,则产生提前唤醒中断,如果真进入了这个中断的话,就说明程序肯定是出问题了,那么在中断服务程序里面我们就需要做最重要的工作,比如保存重要数据,或者报警等,这个中断我们也叫它死前中断。
  • 窗口值:我们知道窗口看门狗必须在计数器的值在一个范围内才可以喂狗,其中下窗口的值是固定的 0x40,上窗口的值可以改变,具体的由配置寄存器 CFR 的位 6:0 W[6:0]设置。其值必须大于 0x40,如果小于或者等于 0x40就是失去了窗口的价值,而且也不能大于计数器的值,所以必须得小于 0x7F。那窗口值具体要设置成多大?这个得根据我们需要监控的程序的运行时间来决定。如果我们要监控的程序段 A 运行的时间为 Ta,当执行完这段程序之后就要进行喂狗,如果在窗口时间内没有喂狗的话,那程序就肯定是出问题了。一般计数器的值 TR设置成最大 0x7F,窗口值为 WR,计数器减一个数的时间为 T,那么时间: (TR-WR)*T 应该稍微大于 Ta即可,这样就能做到刚执行完程序段 A之后喂狗,起到监控的作用,这样也就可以算出 WR的值是多少。
  • 计算看门狗超时时间

        从图我们知道看门狗超时时间:Twwdg = Tpclk1 x 4096 x2^wdgtb x (T[5:0] + 1) ms,当 PCLK1 = 30MHZ时,WDGTB 取不同的值时有最小和最大的超时时间。下面讲解一下,最大WDGTB=0是怎么算的。递减计数器有 7 位 T[6:0] ,当位 6变为 0的时候就会产生复位,实际上有效的计数位是 T[5:0],而且 T6 必须先设置为 1。如果T[5:0]=0 时,递减计数器再减一次,就产生复位了,那这减一的时间就等于计数器的周期=1/CNT_CK = Tpclk1 * 4096 * (2^WDGTB) = 1/30 * 4096 *2^0 = 136.53us,这个就是最短的超时时间。如果 T[5:0]全部装满为 1,即 63,当他减到 0x40变成 0x3F时,所需的时间就是最大的超时时间=113.7*2^5=136.53*64=8.74ms。同理,当 WDGTB 等于 1/2/3 时,代入公式即可。

        WWDG 一般被用来监测,由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。比如一个程序段正常运行的时间是 50ms,在运行完这个段程序之后紧接着进行喂狗,如果在规定的时间窗口内还没有喂狗,那就说明我们监控的程序出故障了,跑飞了,那么就会产生系统复位,让程序重新运行。

准备

MDK5 开发环境。

STM32F4xx HAL库。

STM32F407 开发板。

STM32F4xx 参考手册。

STM32F407 开发板电路原理图。

步骤

  • 首先创建WWDG_Init()函数,初始化窗口看门狗并使能中断及优先级。配置计数器值为0x7F(127,最大值),配置窗口值为0x50(80,0x40为最小值),计数器分频为8分频,则计数器频率为(PCLK (42MHz) / 4096) / 8  约等于1281Hz,则计数器记一次时间为780us,则有780 * (127 - 80) = 36.6ms < 刷新窗口 < ~780 * 64(0x40) = 49.9ms。
WWDG_HandleTypeDef WWDG_Handle; // 窗口看门狗初始化句柄
/* 
*窗口看门狗配置函数
*递减计时器值:Counter = 0x7F(127, 最大值)
*	 窗口值:Window = 0x50(80, 0x40为最小值)
* 计数器频率:WWDG counter clock = (PCLK(42MHz)/4096)/8 = 约等于1281Hz 
*则计数器记一次时间为:780us
*则有:780 * (127 - 80) = 36.6ms < 刷新窗口 < ~780 * 64 = 49.9ms
*/
void WWDG_Init(void)
{
	__HAL_RCC_WWDG_CLK_ENABLE(); // 窗口看门狗时钟使能

	WWDG_Handle.Instance = WWDG; // 窗口看门狗基地址
	WWDG_Handle.Init.Counter = 0x7F; // 计时器值初始化为最大 127
	WWDG_Handle.Init.Prescaler = WWDG_PRESCALER_8; // 预分频值 8分频
	WWDG_Handle.Init.Window = 0x50; // 窗口值 80
	WWDG_Handle.Init.EWIMode = WWDG_EWI_ENABLE; // 看门狗使能
	HAL_WWDG_Init(&WWDG_Handle);  // 窗口看门狗初始化

	HAL_NVIC_SetPriority(WWDG_IRQn, 2, 3); // 配置窗口看门狗中断优先级
	HAL_NVIC_EnableIRQ(WWDG_IRQn); 	// 使能窗口看门狗
}
  • 配置窗口看门狗中断服务函数。当递减计数器减到0x40的时候,会产生一个中断,这个中断我们称它为死前中断或者遗嘱中断。在本实验的中断服务函数中我们开启蜂鸣器。
// 窗口看门狗遗嘱中断,当计数器的值减到0X40后,产生的中断
void WWDG_IRQHandler(void)
{
	HAL_WWDG_IRQHandler(&WWDG_Handle);
}

// 中断回调函数
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef* hwwdg)
{
	BUZZER_ON;
}
  • 定义喂狗函数。喂狗就是重新刷新递减计数器的值防止系统复位,喂狗一般是在主函数中喂。
// 喂狗函数
void WWDG_Refresh(void)
{
	HAL_WWDG_Refresh(&WWDG_Handle);
}
  • 主函数main程序如下:

        第一步:定义存储计数器当前值和窗口上限值变量。

        第二步:初始化系统时钟、蜂鸣器,开启蜂鸣器并延时1秒钟。

        第三步:初始化窗口看门狗并读取窗口上限值。

        第四步:在while()循环中首先关闭蜂鸣器,然后不断读取计数器的值,当计数器的值减小到小于上窗口值的时候,我们喂狗,让计数器重新计数。

uint16_t wwdg_tr; // 读取计数器当前值
uint16_t wwdg_wr; // 读取窗口上限值

int main()
{
	CLOCK_Init(); // 时钟初始化
	BUZZER_Init(); // 蜂鸣器初始化
	WWDG_Init(); // 窗口看门狗初始化
	
	BUZZER_ON; // 开启蜂鸣器
	
	// 读取窗口上限值
	wwdg_wr= WWDG->CFR & 0X7F;
	
	while(1)
	{
		BUZZER_OFF; // 关闭蜂鸣器

		// 读取计数器当前值
		wwdg_tr = WWDG->CR & 0X7F;
		
		// 当计数器的值小于窗口上限值时,触发喂狗事件
		if(wwdg_tr < wwdg_wr)
		{
			WWDG_Refresh();
		}
	}
}

现象

        将程序下载到开发板中,蜂鸣器响起,一段时间后关闭,之后蜂鸣器将不再响起,说明系统没有产生复位。

版权声明:本文为CSDN博主「Mr.奚」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xhj1021/article/details/122922309

生成海报
点赞 0

Mr.奚

我还没有学会写个人说明!

暂无评论

相关推荐

智能车浅谈——抗干扰技术软件篇

软件抗干扰技术 前面介绍了一些硬件抗干扰技术,不难发现,要做好一个完美的硬件系统是需要花大心思的,而且很多硬件抗扰方案都需要借助一些元器件来实现,这在一定程度上增加了费用,

CMSIS/FreeRTOS中队列(Queue)的使用

在有流式数据处理的嵌入式系统中,队列(Queue)是几乎必然被使用的工具,但大多数开发板提供的FreeRTOS例程是不包含队列的,要使用还要自己研究。这次我的样例把串口收到的数据按字节塞入队列&#xff

一篇博客实现嵌入式入门

前言 今天是参加百问网7天智能家居项目的第二天,感谢黄老师的教学。通过今天的学习,再次温习了之前学习的基础知识,同时对MCU也有了新的理解和学习的方法。 最小系统和C语言 最小系统 单片机的最小系