×
单片机 > 单片机程序设计 > 详情

stm32CubeMx中实现窗口看门狗功能

发布时间:2020-05-19 发布时间:
|

stm32CubeMx..........多数嵌入式编程人员可能已程习惯使用stm32的库开发方式来实现功能,库版本v3.5.0本人之前也一直使用,开始使用stm32CubeMx开发方式,发现和原先库开发方式与很多不同,实现方法也有区别。本文旨在将个人在stm32CubeMx开发方式中总结的一些经验写出来,供大家参考。


对于看门狗而言,stm32中有两种,分为独立看门狗(IWDG)和窗口看门狗(WWDG),在此大概介绍下两条警犬,本文重点介绍窗口看门狗。


独立看门狗:独立看门狗(IWDG)由专用的40kHz的低速时钟驱动,即使主时钟发生故障它也仍然有效。IWDG最适合应用于那些需要看门狗作为一个在主程序之外,能够完全独立工作,并且对时间精度要求较低的场合。


窗口看门狗:窗口看门狗通常被用来监测由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。通俗说就是会产生两个复位。复位条件:(1)当计数器的数值从0x40减到0x3F;(2)当刷新看门狗时计数器的数值大于窗口上限值时。满足任何一条都可以产生复位信号。通常情况下设置窗口上限值为0x7F,下限值默认为0x40,计数器向下数到0x40就会产生中断,下个910us后变为0x3F就会复位系统。也就是喂狗操作不能早喂,即大于窗口值时会发生复位;喂的晚了,即计数器的数值从0x40减到0x3F时没有及时喂狗,也会产生复位。


实验说明:板子型号为stm32F103VET6, 每次喂狗并通过串口打印出来

下面来看下在stm32CubeMx中窗口看门狗的实现。

1、在stm32cubemx中设值

我们设置分频系数为8;窗口值为0x5f;计数值为0x7f;其中窗口默认下限值为0x40。并打开中断,打开中断后,会置1中断位,如图:

(2)写WWDG初始化函数

void WWDG_Init(void)
{
__WWDG_CLK_ENABLE(); //使能WWDG时钟
   
MX_WWDG_Init(); //调用系统初始化函数,也就是我们在图形界面设置好值后,会将我们刚才设置的值转化为代码。在本函数里直接调用即可


__HAL_WWDG_CLEAR_FLAG(&hwwdg, WWDG_FLAG_EWIF);  // 开启中断前,先清除中断标志位

HAL_WWDG_Start_IT(&hwwdg);   //设置中断标志位,并开启中断,

}

(3)我们再来开下在中断函数,cubemx的中断函数处理和库开发方式还是有区别的。

/**
* @brief This function handles Window watchdog interrupt.
*/
void WWDG_IRQHandler(void)
{
  /* USER CODE BEGIN WWDG_IRQn 0 */


  /* USER CODE END WWDG_IRQn 0 */
  HAL_WWDG_IRQHandler(&hwwdg);
  /* USER CODE BEGIN WWDG_IRQn 1 */


  /* USER CODE END WWDG_IRQn 1 */
}

我们看到在它的中断函数里调用了一个函数, HAL_WWDG_IRQHandler(&hwwdg); 我们再来看这个函数,在该函数里出现了一个在cubemx方式里独有的,回调函数,当中断开启,并且中断标志位满足后将会调用该函数,而我们的操作将会在这里实现。


void HAL_WWDG_IRQHandler(WWDG_HandleTypeDef *hwwdg)

  /* Check if Early Wakeup Interrupt is enable */
  if(__HAL_WWDG_GET_IT_SOURCE(hwwdg, WWDG_IT_EWI) != RESET)
  {
    /* Wheck if WWDG Early Wakeup Interrupt occurred */
  if(__HAL_WWDG_GET_FLAG(hwwdg, WWDG_FLAG_EWIF) != RESET)
  {
    /* Early Wakeup callback */ 
    HAL_WWDG_WakeupCallback(hwwdg);
    
    /* Change WWDG peripheral state */
    hwwdg->State = HAL_WWDG_STATE_READY; 
    
      /* Clear the WWDG Early Wakeup flag */
    __HAL_WWDG_CLEAR_FLAG(hwwdg, WWDG_FLAG_EWIF);
    
    /* Process Unlocked */
    __HAL_UNLOCK(hwwdg);
  }

}

(4)下面我们来讨论看门狗的喂狗时间,很容易计算在stm32f103系列里窗口看门狗的最大喂狗时间也就58ms,在一些程序里我们没必要这么密集的去喂狗。那么如何增大喂狗时间呢。搜集了网上的一些方法后,本人根据具体事例实现了一个增大看门狗喂狗时间的方法:就是在中断函数中再做一个额外计数器,如果计数器没有达到设定值,就就行喂狗操作,同时使设定值加1,当计数器达到设定值时,就不加载喂狗定时器初值,这时看门狗定时器就会从从0x40减到0x3F产生系统复位。使用这个方法可以将定时时间拓展到 58ms*额外计数器设定值,定个几十秒都不是问题。 当达到计数值后如果我们清零计数值,那么看门狗系统就会复位,所以我们只要在主函数里定期的将该计数值清零,也就是变相的增大了喂狗时间。下面具体看事例:

每次产生看门狗中断都会调用回调函数,我在回调函数里做如下操作:

/*****************************看门狗回调函数********************************/
void HAL_WWDG_WakeupCallback(WWDG_HandleTypeDef* hwwdg)
{
if(time <=50)
{
HAL_WWDG_Refresh(hwwdg, WWDG_CNT); //喂狗函数
printf("喂狗 ");    //每喂一次狗,打印一次,无实际作用
time++;
}
}


/**************************main函数中部分函数********************************/

  while (1)
  {
if(time > 50)
{
time = 0;
printf("time清零 ");
}
  }


我设置看门狗最大喂狗时间为58ms,那么计数50次,大概是2.9s时间,也就是我在主函数中必须在2.9s内,只要对计数器清零,系统就不会复位了。相应的可以把计数值设置更大,这就根据个人需要了。这样是不是变相的增大喂狗时间了。

下面是我的串口打印效果:



大家看一下是不是每喂一次狗就会打印一个“喂狗”,同时在11点55分20秒有一次time清零,到11点55分23秒有一次time清零,是不是间隔大概3秒了。



好了,本人也是刚开始使用stm32CubeMx开发,如果内容中有问题,希望指出来,共同进步




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
基于arm的指纹识别门禁系统是如何设计的