8.STM32CubeIDE窗口看门狗实验

本文详细描述了在STM32F103C8T6平台上使用STM32CubeIDE实现窗口看门狗实验的过程,包括WWDG的工作原理、计数器设置、超时时间计算,以及如何通过硬件和软件操作验证其功能,包括窗口期喂狗、提前唤醒中断喂狗等。
摘要由CSDN通过智能技术生成


前言

使用STM32CubeIDE实现窗口看门狗实验。
硬件:STM32F103C8T6最小系统板 + USB转TTL模块
软件:STM32CubeIDE


一、实验目的

实现窗口看门狗实验,验证窗口期喂狗,可不执行复位
若不及时喂狗,串口输出 “ 独立看门狗复位!”。
预设:计数器初始值为0x7F,窗口上限值为0x5F,预分频系数为8。

二、学习内容

  1. 使用窗口看门狗( WWDG )

三、实践操作

1.窗口看门狗(WWDG)

WWDG简介

WWDG( Windows Watchdog ),窗口看门狗。

本质为能产生能产生系统复位信号提前唤醒中断的计数器。

WWDG特性:

  1. 递减的计数器;
  2. 当递减计数器值从 0x40 ( 64 ) 减到 0x3F ( 63 ) 时复位( 即T6位跳变到0 );
  3. 计数器的值大于 W[6:0] 值时喂狗会复位;
  4. 提前唤醒中断( EWI ):当递减计数器等于 0x40 时可产生

喂狗操作:在窗口期内重装载计数器的值,防止复位

WWDG作用:用于监测单片机程序运行时效是否精准,主要检测软件异常;用于需要精准检测程序运行时间的场合。

WWDG工作原理

工作原理计数器的初始值是用户自己设定的,T[6:0]共7位,最大为0x7F(1111111);
窗口上限值也是用户自己设定的,W[6:0]共7位,最大为0x7F(1111111);
当计数值从初始值递减到0x40( 无法修改 )时,可产生提前唤醒中断( EWI );
窗口下限值为0x3F( 无法修改 ),当计数值从初始值递减到窗口下限值时,产生复位;
可以考虑在提前唤醒中断中进行喂狗操作
在窗口期内可以喂狗( 窗口上限值 ~ 窗口下限值 );在非窗口期不可以进行喂狗,否则会产生复位
因此窗口期一定要满足W[6:0] ≥ 窗口期 > 0x3F

所以窗口看门狗有两种情况会产生复位:1.到窗口下限值了还没喂狗;2.在非窗口期强行喂狗

强调的是程序运行时间的精准,多一点或者少一点都有可能导致复位!

WWDG超时时间计算

超时时间
其中:
Tout 是WWDG超时时间;
fWWDG 是WWDG的时钟频率,STM32F103系列的fWWDG为36MHz( PCLK1 );
2^WDFGTB 是预分频系数数值( 1,2,4,8 )
T[5:0] 是WWDG_CR寄存器后6位的值( 0~63 )

STM32F103的窗口看门狗超时时间表

预分频系数数值WDGTB最小超时值(us)最大超时值(ms)
101137.28
2122714.56
4245529.12
8391058.25

IWDG与WWDG的主要区别(STM32F103系列)

对比点IWDGWWDG
时钟源LSI(40KHz),独立RC振荡器提供PCLK1(36MHz),外部高速晶振(8MHz)提供
复位条件递减计数到0计数值大于W[6:0]值喂狗/递减计数到0x3F
中断递减计数到0x40可产生提前唤醒中断( EWI )
递减计数器位数12位(max:4096~0)7位(max:127~63)
应用场景防止程序跑飞,死循环,死机检测程序时效,防止软件异常

具体了解IWDG可移步至上一篇文章:7.STM32CubeIDE独立看门狗实验

3.硬件介绍

硬件:STM32F103C8T6最小系统板 + USB转TTL模块

利用USART2进行串口输出( PA2->USART_TX / PA3->USART_RX )

实物图如下图所示:
实物图
注意:两个设备之间RX->TX / TX->RX

4.软件介绍

首先新建工程并进行初始化配置

在此不进行赘述,详细步骤可移步至之前文章。

与之前文章不同的是,根据预设条件:计数器初始值为0x7F、窗口上限值为0x5F、预分频系数为8,需要配置WWDG,如下图所示:配置WWDG
根据预设条件可以算出,超时时间Tout = 58.25ms,窗口时间为29.12ms,因此喂狗时间为:58.25 > 喂狗时间 ≥ 29.13。
为了防止复位,需要在该时间段进行喂狗或用提前换醒中断进行喂狗。

接下来进行窗口看门狗实验的代码编程

代码逻辑与独立看门狗类似,其中判断是否为WWDG复位可以通过__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST) != RESET判断,因为当RCC_FLAG_WWDGRST这个位为1时,证明是通过WWDG复位的,其他系统复位也有相应的标志位:

#define RCC_FLAG_LSIRDY                  ((uint8_t)((CSR_REG_INDEX << 5U) | RCC_CSR_LSIRDY_Pos))   /*!< Internal Low Speed oscillator Ready */
#define RCC_FLAG_PINRST                  ((uint8_t)((CSR_REG_INDEX << 5U) | RCC_CSR_PINRSTF_Pos))  /*!< PIN reset flag */
#define RCC_FLAG_PORRST                  ((uint8_t)((CSR_REG_INDEX << 5U) | RCC_CSR_PORRSTF_Pos))  /*!< POR/PDR reset flag */
#define RCC_FLAG_SFTRST                  ((uint8_t)((CSR_REG_INDEX << 5U) | RCC_CSR_SFTRSTF_Pos))  /*!< Software Reset flag */
#define RCC_FLAG_IWDGRST                 ((uint8_t)((CSR_REG_INDEX << 5U) | RCC_CSR_IWDGRSTF_Pos)) /*!< Independent Watchdog reset flag */
#define RCC_FLAG_WWDGRST                 ((uint8_t)((CSR_REG_INDEX << 5U) | RCC_CSR_WWDGRSTF_Pos)) /*!< Window watchdog reset flag */
#define RCC_FLAG_LPWRRST                 ((uint8_t)((CSR_REG_INDEX << 5U) | RCC_CSR_LPWRRSTF_Pos)) /*!< Low-Power reset flag */

其中__HAL_RCC_GET_FLAG(__FLAG__)是HAL库自带的检测RCC寄存器中某一个标志位状态的函数,具体如下:

/** @brief  Check RCC flag is set or not.
  * @param  __FLAG__ specifies the flag to check.
  *          This parameter can be one of the following values:
  *            @arg @ref RCC_FLAG_HSIRDY HSI oscillator clock ready.
  *            @arg @ref RCC_FLAG_HSERDY HSE oscillator clock ready.
  *            @arg @ref RCC_FLAG_PLLRDY Main PLL clock ready.
  @if STM32F105xx
  *            @arg @ref RCC_FLAG_PLL2RDY Main PLL2 clock ready.
  *            @arg @ref RCC_FLAG_PLLI2SRDY Main PLLI2S clock ready.
  @elsif STM32F107xx
  *            @arg @ref RCC_FLAG_PLL2RDY Main PLL2 clock ready.
  *            @arg @ref RCC_FLAG_PLLI2SRDY Main PLLI2S clock ready.
  @endif
  *            @arg @ref RCC_FLAG_LSERDY LSE oscillator clock ready.
  *            @arg @ref RCC_FLAG_LSIRDY LSI oscillator clock ready.
  *            @arg @ref RCC_FLAG_PINRST  Pin reset.
  *            @arg @ref RCC_FLAG_PORRST  POR/PDR reset.
  *            @arg @ref RCC_FLAG_SFTRST  Software reset.
  *            @arg @ref RCC_FLAG_IWDGRST Independent Watchdog reset.
  *            @arg @ref RCC_FLAG_WWDGRST Window Watchdog reset.
  *            @arg @ref RCC_FLAG_LPWRRST Low Power reset.
  * @retval The new state of __FLAG__ (TRUE or FALSE).
  */
#define __HAL_RCC_GET_FLAG(__FLAG__) (((((__FLAG__) >> 5U) == CR_REG_INDEX)?   RCC->CR   : \
                                      ((((__FLAG__) >> 5U) == BDCR_REG_INDEX)? RCC->BDCR : \
                                                                              RCC->CSR)) & (1U << ((__FLAG__) & RCC_FLAG_MASK)))

因此可以通过以下代码判断是否为WWDG复位:

  if( __HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST) != RESET )	/* 判断是否为窗口看门狗复位 */
  {
	  printf("窗口看门狗复位!\r\n");
	  __HAL_RCC_CLEAR_RESET_FLAGS();					/* 清除复位标志位 */
  }
  else
  {
	  printf("其他复位!\r\n");
  }

不希望这段代码一直循环,只希望提醒一次,因此需要将其放在主循环while(1)之前。
并且每次复位之后,一定要将WWDG复位标志位置0,否则后面每次复位都会显示是WWDG复位;可通过__HAL_RCC_CLEAR_RESET_FLAGS()函数对复位标志位进行置0。

接下来在主循环while(1)中进行验证
不及时喂狗

  while (1)
  {
	  /* 在主程序中喂狗 */
	  HAL_Delay(60);					/* 58.25 > 喂狗时间 ≥ 29.13 */
	  HAL_WWDG_Refresh(&hwwdg);			/* 喂狗 */
	  printf("已经喂狗!\r\n");

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

通过串口调试助手可以看到:不及时喂狗实验现象
由于不及时喂狗,程序不断地进行WWDG复位,其中打印的其他复位是按下复位键进行区别。

过早喂狗

  while (1)
  {
	  /* 在主程序中喂狗 */
	  HAL_Delay(20);					/* 58.25 > 喂狗时间 ≥ 29.13 */
	  HAL_WWDG_Refresh(&hwwdg);			/* 喂狗 */
	  printf("已经喂狗!\r\n");

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

通过串口调试助手可以看到:过早喂狗由于过早喂狗,程序不断地进行WWDG复位,其中打印的其他复位是按下复位键进行区别。

窗口期喂狗

  while (1)
  {
	  /* 在主程序中喂狗 */
	  HAL_Delay(40);					/* 58.25 > 喂狗时间 ≥ 29.13 */
	  HAL_WWDG_Refresh(&hwwdg);			/* 喂狗 */
	  printf("已经喂狗!\r\n");

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

通过串口调试助手可以看到:窗口期喂狗在窗口期内喂狗,程序不会进行WWDG复位,程序正常运行,其中打印的其他复位是按下复位键进行区别。

提前唤醒中断( EWI )喂狗
首先要使能中断,并配置优先级,如下图所示:配置NVIC
其次需要编写提前唤醒中断回调函数void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)

void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{
	HAL_WWDG_Refresh(hwwdg);			/* 喂狗 */
	printf("中断喂狗!\r\n");
}

在中断喂狗之后,就不需要在主函数中进行喂狗了!
通过串口调试助手可以看到:提前唤醒中断( EWI )喂狗


总结

本篇介绍了如何实现一个窗口看门狗实验,分别从硬件方面与软件方面阐述,在硬件方面主要介绍了硬件组成,在软件方面主要介绍了如何验证窗口看门狗是否喂狗成功,并且分为在主函数内喂狗和提前唤醒中断喂狗。完美完成本文开篇提到的学习任务与功能!

在实际应用中,窗口看门狗往往是检测软件是否发生异常!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值