细说STM32F407单片机窗口看门狗WWDG的原理及使用方法

打印 上一主题 下一主题

主题 853|帖子 853|积分 2559

目录
一、窗口看门狗的工作原理
1、递减计数器
2、窗口值和比较器
3、看门狗的启动
4、提前唤醒停止
二、窗口看门狗的HAL驱动步伐
1、窗口看门狗初始化
2.窗口看门狗刷新
3.EWI停止及其处理
三、不开启EWI的WWDG示例
1、示例功能
2、项目设置
(1) 时钟、Debug
(2)GPIO 
(3) WWDG
(4)NVIC
(5)USART、 CodeGenrator
3、软件设计main.c
4、下载并调试
(1)启动后不按任何键,连续更新
(2) 442ms内按键,更新
(3)442ms~1094ms之间按键,不更新 
(4)1094ms以上按键,更新
四、开启EWI的WWDG示例
1、示例功能、项目配置
2、软件设计
3、下载并调试
(1)不按按任何键
(2)按S2,800ms
(3) 按S3,1200ms
(4)按S4,200ms


        窗口看门狗(Window Watchdog,WWDG)是STM32F407上的另一个看门狗,通常用来监测由外部干扰或不可预见的逻辑条件造成的应用步伐软件故障。
一、窗口看门狗的工作原理

        窗口看门狗的内部结构如图所示。

1、递减计数器

        窗口看门狗内部有一个7位递减计数器,控制寄存器WWDG_CR中的T[6:0]位,是计数器的计数值。7位计数器的时钟信号泉源于PCLK1,看门狗内部起首对PCLK1举行4096分频,然后再颠末可配置的预分频器分频,因此7位递减计数器的时钟频率是:
        
=
/(4096×DIV)
        
是时钟信号PCLK1的频率,4096是看门狗的固定分频系数,DIV是可设置的分频系数,由寄存器WWDG_CFR的WDGTB[1:0]位决定,DIV可取值为1、2、4、8。
        7位递减计数器在T6位由1变为0时,就会使体系产生复位(看门狗必须是激活的,也就是控制寄存器WWDG_CR中的WDGA位是1),也就是计数值由0x40变为0x3F时,产生复位。要制止体系复位,就必须在计数值变为0x3F之前重置计数器,重置计数器的值必须大于0x3F。
        窗口看门狗的递减计数器是自由运行计数器,即使没有开启看门狗,这个计数器也是在计数的。所以,在启动看门狗之前,应该重置计数器的值,以制止由于T6位是0而立刻复位。
2、窗口值和比较器

        在配置寄存器WWDG_CFR中,有个7位的窗口值W[6:0],这个值用来与计数器的当前值T[6:0]举行比较。
        窗口看门狗的工作时序图如图所示。当T[6:0]>W[6:0]时,比较器输出为1,这时不允许重置计数器的值,也就是不允许写WWDG_CR,否则体系复位。只有当T[6:0]≤W[6:0]时,才可以重置计数器的值,如果在T[6:0]变化到0x3F之前没有重置计数器,就会产生体系复位信号。所以,只能在这样一个窗口期重置看门狗计数器,这也是称为“窗口看门狗”的缘故起因。

        根据窗口看门狗的工作特点,在初始化设置时,窗口值W[6:0]必须小于或即是递减计数器的重置值。窗口看门狗的超时(timeout)就是计数器重置后,计数值变化为0x3F的这段时间长度,也就是图中不允许刷新和允许刷新两段的时间长度之和。用户可以根据计数器的时钟信号频率和T[6:0]的重置值计算超时。例如,设置计数器重置值为最大值0x7F,变化到0x3F时的计数周期个数是:
∆=0x7F-0x3F=0x40。

        计数器的时钟周期是:

        所以,看门狗的超时是:

       同样,也可以计算出不允许刷新的时间段的长度。
3、看门狗的启动

        控制寄存器WWDG_CR中的位WDGA用于启动看门狗。体系复位后WDGA被硬件清零,通过向WDGA写1可启动看门狗。别的,启动看门狗后就无法再停止,除非体系复位。
        根据窗口看门狗的特点,可以使用软件使体系立刻复位。具体的操作方法是将WDGA位置1(启动窗口看门狗),并将T6位清零(使看门狗立刻产生复位),也就是设置一个小于0x3F的重置值即可。
4、提前唤醒停止

        窗口看门狗有一个提前唤醒停止(Early Wakeup Interrupt,EWI)事件,如果已开启此停止事件源,且启动了看门狗,在递减计数器的值变为0x40时,就会触发此停止。
        可在此停止服务步伐里执行体系复位之前的一些关键操作,但是执行时间有限,只有一个计数器时钟周期。当然,也可以在此停止服务步伐里重置计数器的值,制止体系复位,但是这样似乎就违背了使用窗口看门狗的初衷。
二、窗口看门狗的HAL驱动步伐

        窗口看门狗的驱动步伐的头文件是stm32f4xx_hal_wwdg.h,WWDG的驱动函数不多。
1、窗口看门狗初始化

        使用函数HAL_WWDG_Init()举行窗口看门狗初始化,其原型界说如下:
  1. WWDG_HandleTypeDef hwwdg;  //WWDG外设对象变量
复制代码
        结构体WWDG_HandleTypeDef的界说如下:
  1. typedef struct
  2. {
  3.     WWDG_TypeDef *Instance;        //寄存器基址
  4.     WWDG_InitTypeDef Init;        //WWDG的参数
  5. }WWDG_HandleTypeDef;
复制代码
        其成员变量Init是结构体类型WWDG_InitTypeDef,包含WWDG的参数。该结构体界说如下,各成员变量意义见表明:
  1. typedef struct
  2. {
  3.     uint32_t Prescaler;        //WWDG时钟预分频系数
  4.     uint32_t Window;        //WWDG窗口值,设定值范围为0x40~0x7E
  5.     uint32_t Counter;        //WWDG自由运行递减计数器的重载值,设定值范围为0×40~0×7F
  6.     uint32_t EWIMode;        //WWDG的EWI中断模式,开启或禁止
  7. }WWDG_InitTypeDef;
复制代码
2.窗口看门狗刷新

        函数HAL_WWDG_Refresh()用于刷新窗口看门狗,其原型界说如下:
  1. HAL_StatusTypeDef HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg);
复制代码
        其功能就是将计数器重置值加载到看门狗的递减计数器,以制止看门狗触发体系复位。但只能在允许刷新时间段才能刷新看门狗。
3.EWI停止及其处理

        WWDG有一个全局停止,只有一个提前唤醒停止(EWI)事件。驱动步伐头文件界说了EWI停止事件使能位的宏,也作为停止事件类型界说。
  1. #define WWDG_IT_EWI WWDG_CFR_EWI        //EWI中断事件使能位,也作为中断事件类型
复制代码
         有一个宏函数用于开启EWI停止事件,即
  1. __HAL_WWDG_ENABLE_IT(__HANDLE__,__INTERRUPT__)
复制代码
        参数__HANDLE__是WWDG对象指针,__INTERRUPT__就使用WWDG_IT_EWI作为参数值。EWI停止事件开启后就不能关闭,只能在硬件复位时才关闭,所以没有关闭EWI停止事件的函数。
        WWDG全局停止ISR里调用的通用处理函数是HAL_WWDG_IRQHandler(),对应于EWI事件停止的回调函数是HAL_WWDG_EarlyWakeupCallback(),其原型界说如下:
  1. void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg);
复制代码
        若要对EWI事件停止做出处理,重新实现这个回调函数即可。
三、不开启EWI的WWDG示例

1、示例功能

        本文作者旨在先容怎样WWDG及用法。继续使用旺宝红龙开发板STM32F407ZGT6 KIT V1.0。示例功能:看门狗在启动或上次刷新后,在442ms之内不能再刷新,在443ms至1049ms之内可以刷新看门狗,如果凌驾1049ms没有刷新看门狗,看门狗就会使体系复位。
        使用开发板上的3个按键,按下案件后分别执行:在允许刷新的时间段内刷新、超时后刷新、在不允许刷新的时间段内刷新。LED1~LED3分别用于动作指示。
  1. //显示菜单
  2. [S2]KeyUp    = 在允许刷新时间段内,看门狗不会触发复位.         LED1闪烁
  3. [S3]KeyDown  = 超时,看门狗会触发系统复位.                    LED2闪烁
  4. [S4]KeyLeft  = 在不允许刷时间段内,刷新看门狗会导致系统复位.    LED3闪烁
复制代码
        本示例不开启EWI停止。 

        部分内容需要参考本文作者写的其他文章。参考文章:细说STM32F407单片机独立看门狗IWDG的原理及使用方法-CSDN博客  https://wenchm.blog.csdn.net/article/details/145159637 
2、项目设置

(1) 时钟、Debug

         设置Debug接口为Serial Wire,设置HSE为Crystal/Ceramic Resonator
        配置时钟树,设置HSE为8MHz,HCLK为32MHz,设置APB1 Prescaler为16,使PCLK1为2MHz。这是由于窗口看门狗要用到PCLK1时钟,使PCLK1为2MHz是为得到一个较低频率时钟信号,用于看门狗的递减计数器,便于观察步伐运行效果。 
 

(2)GPIO 

        本示例要用到两个LED,配置PA6和PA4引脚,设置初始输出为高电平,两个LED的GPIO引脚的配置效果如图所示,仍旧使用keyled.h中的LED驱动函数。

(3) WWDG

        只需激活WWDG即可,参数设置部分的几个参数决定看门狗的特性。
 



  • WWDG counter clock prescaler,看门狗计数器预分频系数,有1、2、4、8几个可选值。
  • WWDG window value,窗口值,也就是W[6:0]的值。这个值必须小于计数器的重置值,也必须大于0x3F(十进制值63)。
  • WWDG free-running downcounter value,递减计数器T[6:0]的重置值,最大值为127(也就是0x7F),必须大于W[6:0]的值。根据设置的参数以及PCLK1为2MHz,可以计算出看门狗的超时为
         

        计数器重置后不允许刷新的时间段长度是
         

        对照WWDG工作原理图,这两个时间对看门狗的意义:看门狗在启动或上次刷新后,在442ms之内不能再刷新,在443ms至1049ms之内可以刷新看门狗,如果凌驾1049ms没有刷新看门狗,看门狗就会使体系复位。


  • Early wakeup interrupt,是否开启提前唤醒停止。这里开启EWI停止。还需要在WWDG的NVIC Settings页面开启WWDG的全局停止,使用默认的优先级即可。
(4)NVIC

        在WWDG的NVIC Settings页面开启WWDG的全局停止,使用默认的优先级。

(5)USART、 CodeGenrator

         与参考文章相同。
3、软件设计main.c

  1. /* USER CODE BEGIN Includes */
  2. #include "keyled.h"
  3. #include <stdio.h>
  4. /* USER CODE END Includes */
复制代码
  1. /* USER CODE BEGIN 2 */
  2.   //系统复位、初始状态
  3.   printf("Demo21_WWDG: Windows Watchdog\r\n\r\n");
  4.   //显示菜单
  5.   printf("[S2]KeyUp    = 在允许刷新时间段内,看门狗不会触发复位.\r\n");
  6.   printf("[S3]KeyDown  = 超时,看门狗会触发系统复位.\r\n");
  7.   printf("[S4]KeyLeft  = 在不允许刷时间段内,刷新看门狗会导致系统复位.\r\n\r\n");
  8.   // MCU output low level LED light is on
  9.   LED1_OFF();
  10.   LED2_OFF();
  11.   LED3_OFF();
  12.   LED4_OFF();
  13.   /* USER CODE END 2 */
复制代码
  1.     /* USER CODE BEGIN 3 */
  2.         KEYS curKey = ScanPressedKey(KEY_WAIT_ALWAYS);
  3.         switch(curKey)
  4.         {
  5.                 //1. 在允许刷新时间段内,看门狗不会触发复位,LED1闪烁
  6.                 case KEY_UP:
  7.                 {
  8.                         LED1_Toggle();
  9.                           LED2_OFF();
  10.                           LED3_OFF();
  11.                           HAL_Delay(800);
  12.                           HAL_WWDG_Refresh(&hwwdg);         //刷新看门狗,也就是重置计数器的值
  13.                           printf("The watchdog will not trigger a reset during the allowed refresh period.\r\n\r\n");
  14.                           break;
  15.                 }
  16.                 //2. 超时,看门狗会触发系统自动复位,LED2亮
  17.                 case KEY_DOWN:
  18.                 {
  19.                           LED1_OFF();
  20.                           LED2_ON();
  21.                           LED3_OFF();
  22.                           printf("Timeout, the watchdog will trigger a reset automatically.\r\n\r\n");
  23.                           HAL_Delay(1200);
  24.                           HAL_WWDG_Refresh(&hwwdg);
  25.                           break;
  26.                 }
  27.                 //3. 在不允许刷时间段内,刷新看门狗会导致系统复位,LED3亮
  28.                 case KEY_LEFT:
  29.                 {
  30.                           HAL_Delay(200);
  31.                           LED1_OFF();
  32.                           LED2_OFF();
  33.                           LED3_ON();
  34.                           HAL_Delay(200);
  35.                           HAL_WWDG_Refresh(&hwwdg);         //刷新看门狗,也就是重置计数器的值
  36.                           printf("During the period of time when refresh is not allowed,\r\n");
  37.                           printf("refreshing the watchdog will cause the system to reset.\r\n\r\n");
  38.                           break;
  39.                  }
  40.                  default:
  41.                  {
  42.                           printf("Keystroke error, refreshing watchdog will not cause system reset.\r\n\r\n");
  43.                           LED1_OFF();
  44.                           LED2_OFF();
  45.                           LED3_OFF();
  46.                  }
  47.         }
  48.         HAL_Delay(500);                //消除按键抖动影响
  49.   }
  50.   /* USER CODE END 3 */
复制代码
  1. /* USER CODE BEGIN 4 */
  2. int __io_putchar(int ch)
  3. {
  4.         HAL_UART_Transmit(&huart6,(uint8_t*)&ch,1,0xFFFF);
  5.         return ch;
  6. }
  7. /* USER CODE END 4 */
复制代码
4、下载并调试

        调试的时间,按键按下后不要抬起。 
(1)启动后不按任何键,连续更新

         启动后不按任何键,体系连续启动,串口助手连续体现启动信息,这是由于WWDG的窗口值100,重置值127,当减计数到100后,体系主动重启。

(2) 442ms内按键,更新

        在执行LED3_ON()前后各延时200ms是为了看到LED3的闪烁效果,这两个延时合计400ms,还在不允许刷新时间段内(小于442ms),这时调用HAL_WWDG_Refresh()刷新看门狗会使体系复位,后面如果有步伐也是不会被执行的。 

(3)442ms~1094ms之间按键,不更新 

        看门狗在允许刷新的时间段内及时刷新。如果在while循环内调用HAL_Delay(800)延时800ms,然后调用HAL_WWDG_Refresh()刷新看门狗,则可以观察到LED1不停闪烁。由于延时800ms后进入允许刷新的时间段(大于442ms),也没有凌驾看门狗的超时时间(1049ms),这时间调用HAL_WWDG_Refresh()是可以刷新看门狗的,步伐能不停正常运行,所以LED1闪烁,闪烁周期为800ms。
 



(4)1094ms以上按键,更新

        看门狗超时是主动复位的。如果将步伐中的延时改为1200ms,则运行时会看到LED1不停亮着。由于在延时1200ms的过程中,看门狗已经超时导致体系复位,while循环里使LED1输出翻转的代码不会被执行。

四、开启EWI的WWDG示例

1、示例功能、项目配置

        除WWDG开启EWI停止外,别的都与三相同。
 

2、软件设计

        在不开启EWI的时间,步伐下载后,即使不按任何键,WWDG的减计数器减到阈值后也会主动重置,现象就是串口助手接二连三底体现更新,一般情况下,这不是设计者的设计目标。
        开启EWI后,在EWI的回调函数里执行计数器重置。那么久办理了上面不需要的连续刷新WWDG的现象了。 
  1. /* USER CODE BEGIN 4 */
  2. // EWI中断事件回调函数
  3. void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
  4. {
  5.         LED4_Toggle();
  6.         HAL_WWDG_Refresh(hwwdg); //在此刷新看门狗,看门狗也是能被刷新的
  7. }
  8. int __io_putchar(int ch)
  9. {
  10.         HAL_UART_Transmit(&huart6,(uint8_t*)&ch,1,0xFFFF);
  11.         return ch;
  12. }
  13. /* USER CODE END 4 */
复制代码
        看门狗的EWI停止是在递减计数器的值变为0x40时触发的,而递减计数器的值变为0x3F时就会导致体系主动复位。所以,EWI停止相称于在体系复位之前的一个预警,用户可以在此停止里做一些告急处理,例如关闭某个开关,但是处理时间只有1个计数周期。

3、下载并调试

(1)不按按任何键


(2)按S2,800ms

 

(3) 按S3,1200ms

 

(4)按S4,200ms

 


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

何小豆儿在此

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表