你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32F103看门狗功能实现

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

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

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

  看门狗主要是用来对系统运行状态进行监控的,以免系统被干扰后代码跑飞了,导致系统混乱。看门狗的使用也比较简单,下面就分别来看一下独立看门狗和窗口看门狗的使用方法。

独立看门狗

  1. //初始化独立看门狗
  2. //prer:分频数:0~7(只有低 3 位有效!)
  3. //分频因子=4*2^prer.但最大值只能是 256!
  4. //rlr:重装载寄存器值:低 11 位有效.
  5. //时间计算(大概):Tout=((4*2^prer)*rlr)/40 (ms).
  6. void IWDG_Init(u8 prer,u16 rlr)
  7. {
  8.         // 1、取消寄存器写保护 写0x5555
  9.         IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
  10.         // 2、设置独立看门狗预分频系数
  11.         IWDG_SetPrescaler(prer);
  12.         // 3、设置独立看门狗重装载值
  13.         IWDG_SetReload(rlr);;
  14.         // 4、重载计数值喂狗 写0xAAAA
  15.         IWDG_ReloadCounter();
  16.         // 5、启动看门狗     写0xCCCC
  17.         IWDG_Enable();
  18. }
  19. void IWDG_Feed(void)
  20. {
  21.         IWDG_ReloadCounter();
  22. }
复制代码

独立看门狗的初始化很简单,主要就是设置一下喂狗的时间。然后在程序运行过程中不停的喂狗。

  1. int main(void)
  2. {
  3.     u8 key = 0;
  4.     delay_init();       //延时函数初始化
  5.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  6.     LED_Init();
  7.     KEY_Init();
  8.     IWDG_Init(4, 625);        //溢出时间为1s  (4*2^4)*625/40=1000ms

  9.     LED0 = 1;
  10.     LED1 = 1;
  11.     delay_ms(500);
  12.     LED0 = 0;
  13.     LED1 = 0;

  14.     while(1)
  15.     {
  16.         key = KEY_Sacn(1);
  17.         if( key == WKUP_PRES)
  18.         {
  19.             IWDG_Feed();
  20.         }
  21.         delay_ms(10);
  22.     }
  23. }
复制代码

这里通过一个按键来模拟喂狗,当按键按一次,就会喂狗一次。如果按键超过喂狗时间没有按下时,独立看门狗就会使系统复位。

窗口看门狗

  1. u8 WWDG_CNT = 0x7f;
  2. void WWDG_NVIC_Init(void)
  3. {
  4.     NVIC_InitTypeDef NVIC_InitStructure;
  5.     NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;
  6.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
  7.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
  8.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  9.     NVIC_Init(&NVIC_InitStructure);
  10. }

  11. //初始化窗口看门狗
  12. //tr :T[6:0],计数器值
  13. //wr :W[6:0],窗口值
  14. //fprer:分频系数(WDGTB),仅最低 2 位有效
  15. //Fwwdg=PCLK1/(4096*2^fprer)
  16. void WWDG_Init(u8 tr, u8 wr, u32 fprer)
  17. {
  18.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); //时钟使能
  19.     WWDG_CNT = tr & WWDG_CNT;
  20.     WWDG_SetPrescaler(fprer);                        //设置预分频值
  21.     WWDG_SetWindowValue(wr);                        //设置窗口值 上窗口值  与喂狗间隔没关系
  22.     WWDG_Enable(WWDG_CNT);                        //使能看门狗,设置计数值
  23.     WWDG_ClearFlag();                                //清除提前唤醒中断
  24.     WWDG_NVIC_Init();                                //设置中断优先级
  25.     WWDG_EnableIT();                                //开启窗口看门狗中断
  26. }
  27. void WWDG_Set_Counter(u8 cnt)
  28. {
  29.     WWDG_Enable(cnt);                                //使能看门狗,设置计数值
  30. }
  31. void WWDG_IRQHandler(void)
  32. {
  33.     WWDG_SetCounter(WWDG_CNT);                       //喂狗
  34.     WWDG_ClearFlag();                                //清除提前唤醒中断
  35.     LED0=!LED0;
  36. }
复制代码

由于窗口看门狗的喂狗时间很短,在程序运行过程中很难判断出什么时候该喂狗,所以这里喂狗使用中断来执行,在需要喂狗的时候,直接触发中断,在中断中进行喂狗,每喂一次狗,LED就取反一次。通过观察LED的闪烁就可看出中断函数的执行情况。

  1. int main(void)
  2. {
  3.     u8 key = 0;
  4.     delay_init();       //延时函数初始化
  5.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  6.     LED_Init();
  7.     KEY_Init();
  8.     //IWDG_Init(4, 625);        //溢出时间为1s  (4*2^4)*625/40=1000ms

  9.     LED0 = 1;
  10.     LED1 = 1;
  11.     delay_ms(500);
  12.     LED0 = 0;
  13.     LED1 = 0;
  14.         
  15.     //窗口看门狗喂狗间隔 只和 tr 低6位有关  wr 可以设置为0x40---0x7f 之间的任意值
  16.     // 4096*2^3*64/36000000 = 58.25ms   (64为0x7f 低6位值)
  17.     WWDG_Init(0x7f, 0x7f, WWDG_Prescaler_8); //计数器值7f,窗口寄存器5f,分频数为8
  18.         
  19.     // 4096*2^3*31/36000000 =28.22ms   (31为0x4f 低6位值)
  20.     //WWDG_Init(0x5f, 0x5f, WWDG_Prescaler_8);
  21.         
  22.    // 4096*2^3*15/36000000 =13.65ms   (15为0x4f 低6位值)
  23.     //WWDG_Init(0x4f, 0x5f, WWDG_Prescaler_8);        
  24.         
  25.     // 4096*2^3*1/36000000 =910us  (1为0x41 低6位值)  窗口最小值为0x40
  26.     //WWDG_Init(0x41, 0x5f, WWDG_Prescaler_8);
  27.     while(1)
  28.     {      
  29.     }
  30. }
复制代码

在主函数中通过设置不同的溢出时间来观察LED灯的闪烁频率。


收藏 评论0 发布时间:2022-3-19 20:51

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版