当前位置:   article > 正文

学习记录:使用STM32F1看门狗_stmf1看门狗

stmf1看门狗

目录

前言

一、独立看门狗

1.1、 IWDG主要性能 

1.2、IWDG功能描述 

 1.3、寄存器访问保护

 1.4、配置独立看门狗的步骤

 二、窗口看门狗

2.1、WWDG主要特性 

2.2、WWDG功能描述 

 2.3、窗口看门狗的配置步骤


(参考STM32中文参考手册)

前言

        在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞,而陷入死循环,程序的正常运行被打断,由单片机控制的系统无法继续工作,会造成整个系统的陷入停滞状态,发生不可预料的后果,所以出于对单片机运行状态进行实时监测的考虑,便产生了一种专门用于监测单片机程序运行状态的模块或者芯片,俗称“看门狗”(watchdog) 。

        STM32F10xxx内置两个看门狗,提供了更高的安全性、时间的精确性和使用的灵活性。两个看门狗设备(独立看门狗和窗口看门狗)可用来检测和解决由软件错误引起的故障;当计数器达到给定的超时值时,触发一个中断(仅适用于窗口型看门狗)或产生系统复位。 

一、独立看门狗

         独立看门狗(IWDG)由专用的40Khz低速时钟(LSI)驱动LSI是一个 RC 时钟。即使主时钟发生故障它也仍然有效。窗口看门 狗由从APB1时钟分频后得到的时钟驱动,通过可配置的时间窗口来检测应用程序非正常的过迟 或过早的操作。

         IWDG(独立看门狗)最适合应用于那些需要看门狗作为一个在主程序之外,能够完全独立工作,并且对时间精 度要求较低的场合。WWDG(窗口看门狗)最适合那些要求看门狗在精确计时窗口起作用的应用程序。

1.1、 IWDG主要性能 

        1. 自由运行的递减计数器 ;2.时钟由独立的RC振荡器提供(可在停止和待机模式下工作) ;3.看门狗被激活后,则在计数器计数至0x000时产生复位

1.2、IWDG功能描述 

独立看门狗模块的功能框图

        在键寄存器(IWDG_KR)中写入0xCCCC,开始启用独立看门狗;此时计数器开始从其复位值 0xFFF递减计数。当计数器计数到末尾0x000时,会产生一个复位信号(IWDG_RESET)。 无论何时,只要在键寄存器IWDG_KR中写入0xAAAA, IWDG_RLR中的值就会被重新加载到计数器,从而避免产生看门狗复位 。 

看门狗功能处于VDD供电区,即在停机和待机模式时仍能正常工作 

 1.3、寄存器访问保护

         IWDG_PR和IWDG_RLR寄存器具有写保护功能。要修改这两个寄存器的值,必须先向IWDG_KR寄存器中写入0x5555。以不同的值写入这个寄存器将会打乱操作顺序,寄存器将重新被保护。重装载操作(即写入0xAAAA)也会启动写保护功能。

        状态寄存器指示预分频值和递减计数器是否正在被更新。

        预分频寄存器(IWDG_PR),该寄存器用来设置看门狗时钟的分频系数, 最低为 4,最高位 256,该寄存器是一个 32 位的寄存器,但是我们只用了最低 3 位,其他都是保留位。

        重装载寄存器。该寄存器用来保存重装载到计数 器中的值。该寄存器也是一个 32 位寄存器,但是只有低 12 位是有效的 。

 

 1.4、配置独立看门狗的步骤

        只要对三个寄存器进行相应的配置,我们就可以启动 STM32F1x的独立看门狗。

         下图的时间是按照40kHz时钟给出。实际上,MCU内部的RC频率会在30kHz到60kHz之间变化。 此外,即使RC振荡器的频率是精确的,确切的时序仍然依赖于APB接口时钟与RC振荡器时钟之间的相位差,因此总会有一个完整的RC周期是不确定的。

        溢出时间计算:

                   Tout=((4×2^prer) ×rlr) /40 (M3)

步骤

        1.取消寄存器写保护:      

 IWDG_WriteAccessCmd();

         2.设置独立看门狗的预分频系数,确定时钟:

IWDG_SetPrescaler();

        3. 设置看门狗重装载值,确定溢出时间:

 IWDG_SetReload();

         4. 使能看门狗

 IWDG_Enable();

        5. 应用程序喂狗:

  IWDG_ReloadCounter();

iwdg.c程序如下所示:

  1. #include "wdg.h"
  2. /*初始化独立看门狗
  3. prer:分频数:0~7(只有低3位有效!)
  4. 分频因子=4*2^prer.但最大值只能是256!
  5. rlr:重装载寄存器值:低11位有效.
  6. 时间计算(大概):Tout=((4*2^prer)*rlr)/40 (ms).*/
  7. void IWDG_Init(u8 prer,u16 rlr)
  8. {
  9. IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //使能对寄存器IWDG_PR和IWDG_RLR的写操作
  10. IWDG_SetPrescaler(prer); //设置IWDG预分频值:设置IWDG预分频值为64
  11. IWDG_SetReload(rlr); //设置IWDG重装载值
  12. IWDG_ReloadCounter(); //按照IWDG重装载寄存器的值重装载IWDG计数器
  13. IWDG_Enable(); //使能IWDG
  14. }
  15. //喂独立看门狗
  16. void IWDG_Feed(void)
  17. {
  18. IWDG_ReloadCounter();//reload
  19. }

 iwdg.h程序如下所示:

  1. #ifndef __WDG_H
  2. #define __WDG_H
  3. #include "sys.h"
  4. void IWDG_Init(u8 prer,u16 rlr);
  5. void IWDG_Feed(void);
  6. #endif

 main.c程序如下所示:

  1. #include "led.h"
  2. #include "delay.h"
  3. #include "key.h"
  4. #include "sys.h"
  5. #include "usart.h"
  6. #include "wdg.h"
  7. int main(void)
  8. {
  9. delay_init(); //延时函数初始化
  10. LED_Init(); //初始化与LED连接的硬件接口
  11. KEY_Init(); //按键初始化
  12. delay_ms(500); //让人看得到灭
  13. IWDG_Init(4,625); //与分频数为64,重载值为625,溢出时间为1s
  14. LED0=0; //点亮LED0
  15. while(1)
  16. {
  17. if(KEY_Scan(0)==WKUP_PRES)
  18. {
  19. IWDG_Feed();//如果WK_UP按下,则喂狗
  20. }
  21. delay_ms(10);
  22. };
  23. }

 二、窗口看门狗

        对于一般的看门狗,程序可以在它产生复位前的任意时刻刷新看门狗,但这有一个隐患,有可能程序跑乱了又跑回到正常的地方,或跑乱的程序正好执行了刷新看门狗操作,这样的情况下一般的看门狗就检测不出来了;

        如果使用窗口看门狗,程序员可以根据程序正常执行的时间设置刷新看门狗的一个时间窗口,保证不会提前刷新看门狗也不会滞后刷新看门狗,这样可以检测出程序没有按照正常的路径运行非正常地跳过了某些程序段的情况。

        窗口看门狗通常被用来监测,由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。除非递减计数器的值在T6位变成0(WWDG->CR 的第六位)前被刷新,看门狗电路在达到预置的时间周期时,会产生一个MCU复位。在递减计数器达到窗口寄存器(WWDG->CFR)数值之前,如果7位的递减计数器数值(在控制寄存器中)被刷新, 那么也将产生一个MCU复位。这表明递减计数器需要在一个有限的时间窗口中被刷新。 

        T[6:0]就是 WWDG_CR 的低七位,W[6:0]即是 WWDG->CFR 的低七位。T[6:0] 就是窗口看门狗的计数器,而 W[6:0]则是窗口看门狗的上窗口,下窗口值是固定的(0X40)。

         当窗口看门狗的计数器在上窗口值之外被刷新,或者低于下窗口值都会产生复位。 上窗口值(W[6:0])是由用户自己设定的,根据实际要求来设计窗口值,但是一定要确保窗口值大于0X40,否则窗口就不存在了。

2.1、WWDG主要特性 

        可编程的自由运行递减计数器

        条件复位

─ 当递减计数器的值小于0x40,(若看门狗被启动)则产生复位。

─ 当递减计数器在窗口外被重新装载,(若看门狗被启动)则产生复位。

        如果启动了看门狗并且允许中断,当递减计数器等于0x40时产生早期唤醒中断(EWI),它可 以被用于重装载计数器以避免WWDG复位。

2.2、WWDG功能描述 

        如果看门狗被启动(WWDG_CR寄存器中的WDGA位被置’1’), 并且当7位(T[6:0])递减计数器从 0x40翻转到0x3F(T6位清零)时,则产生一个复位。如果软件在计数器值大于窗口寄存器中的数 值时重新装载计数器,将产生一个复位。

 

        应用程序在正常运行过程中必须定期地写入WWDG_CR寄存器以防止MCU发生复位。只有当计数器值小于窗口寄存器的值时,才能进行写操作。储存在WWDG_CR寄存器中的数值必须在 0xFF和0xC0之间:

          ● 启动看门狗 在系统复位后,看门狗总是处于关闭状态,设置WWDG_CR寄存器的WDGA位能够开启看 门狗,随后它不能再被关闭,除非发生复位。

         ● 控制递减计数器递减计数器处于自由运行状态,即使看门狗被禁止,递减计数器仍继续递减计数。当看门狗被启用时,T6位必须被设置,以防止立即产生一个复位。

         T[5:0]位包含了看门狗产生复位之前的计时数目;复位前的延时时间在一个最小值和一个最 大值之间变化,这是因为写入WWDG_CR寄存器时,预分频值是未知的。

         配置寄存器(WWDG_CFR) 中包含窗口的上限值:要避免产生复位,递减计数器必须在其值 小于窗口寄存器的数值并且大于0x3F时被重新装载,描述了窗口寄存器的工作过程。

         另一个重装载计数器的方法是利用早期唤醒中断(EWI)。设置WWDG_CFR寄存器中的WEI 位开启该中断。

        当递减计数器到达0x40时,则产生此中断,相应的中断服务程序(ISR)可以用来加载计数器以防止WWDG复位。在WWDG_SR寄存器中写’0’可以清除该中断。 

 2.3、窗口看门狗的配置步骤

1.上窗口值W[6:0]必须大于下窗口值0x40。否则就无窗口了。

2.窗口看门狗时钟来源PCLK1(APB1总线时钟)分频后。

步骤

        使能看门狗时钟:

RCC_APB1PeriphClockCmd();

         设置分频系数:

WWDG_SetPrescaler();

        设置上窗口值:

WWDG_SetWindowValue();

        开启提前唤醒中断并分组(可选):              

  1. WWDG_EnableIT();  
  2. NVIC_Init();

        使能看门狗:

 WWDG_Enable();

        喂狗:

WWDG_SetCounter();

        编写中断服务函数

   WWDG_IRQHandler();

 wwdg.c程序如下所示:

  1. #include "wdg.h"
  2. #include "led.h"
  3. //保存WWDG计数器的设置值,默认为最大.
  4. u8 WWDG_CNT=0x7f;
  5. /*初始化窗口看门狗
  6. tr :T[6:0],计数器值
  7. wr :W[6:0],窗口值
  8. fprer:分频系数(WDGTB),仅最低2位有效
  9. Fwwdg=PCLK1/(4096*2^fprer). */
  10. void WWDG_Init(u8 tr,u8 wr,u32 fprer)
  11. {
  12. RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); // WWDG时钟使能
  13. WWDG_CNT=tr&WWDG_CNT; //初始化WWDG_CNT.
  14. WWDG_SetPrescaler(fprer);设置IWDG预分频值
  15. WWDG_SetWindowValue(wr);//设置窗口值
  16. WWDG_Enable(WWDG_CNT); //使能看门狗 , 设置 counter .
  17. WWDG_ClearFlag();//清除提前唤醒中断标志位
  18. WWDG_NVIC_Init();//初始化窗口看门狗 NVIC
  19. WWDG_EnableIT(); //开启窗口看门狗中断
  20. }
  21. //重设置WWDG计数器的值
  22. void WWDG_Set_Counter(u8 cnt)
  23. {
  24. WWDG_Enable(cnt);//使能看门狗 , 设置 counter .
  25. }
  26. //窗口看门狗中断服务程序
  27. void WWDG_NVIC_Init()
  28. {
  29. NVIC_InitTypeDef NVIC_InitStructure;
  30. NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn; //WWDG中断
  31. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占2,子优先级3,组2
  32. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //抢占2,子优先级3,组2
  33. NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
  34. NVIC_Init(&NVIC_InitStructure);//NVIC初始化
  35. }
  36. void WWDG_IRQHandler(void)
  37. {
  38. WWDG_SetCounter(WWDG_CNT); //当禁掉此句后,窗口看门狗将产生复位
  39. WWDG_ClearFlag(); //清除提前唤醒中断标志位
  40. LED1=!LED1; //LED状态翻转
  41. }

 wwdg.h程序如下所示:

  1. #ifndef __WDG_H
  2. #define __WDG_H
  3. #include "sys.h"
  4. void WWDG_Init(u8 tr,u8 wr,u32 fprer);//初始化WWDG
  5. void WWDG_Set_Counter(u8 cnt); //设置WWDG的计数器
  6. void WWDG_NVIC_Init(void);
  7. #endif

 main.c程序如下所示:

  1. #include "led.h"
  2. #include "delay.h"
  3. #include "key.h"
  4. #include "sys.h"
  5. #include "usart.h"
  6. #include "wdg.h"
  7. int main(void)
  8. {
  9. delay_init(); //延时函数初始化
  10. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
  11. LED_Init();
  12. KEY_Init(); //按键初始化
  13. LED0=0;
  14. delay_ms(300);
  15. WWDG_Init(0X7F,0X5F,WWDG_Prescaler_8);//计数器值为7f,窗口寄存器为5f,分频数为8
  16. while(1)
  17. {
  18. LED0=1;
  19. }
  20. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/437528?site
推荐阅读
相关标签
  

闽ICP备14008679号