亚博智能论坛  
  
查看: 607|回复: 0

【DIY 经验】看门狗

[复制链接]

该用户从未签到

16

主题

52

帖子

109

积分

菜鸟程序猿

Rank: 2

积分
109
发表于 2017-7-17 12:06:30 | 显示全部楼层 |阅读模式

1、有个7位递减计数器(WWDG->CR),就这个计数器和窗口计数器(WWDG->CFR)决定什么时候喂狗。

     狗喂早了,复位——“早”体现在 计数器值(tr)>窗口值(wr),也就是计数器值还没有减到窗口值以下;

2、当 0x40 < 计数器值(tr) < 窗口值(wr) 时,这时候最适合喂狗了,也只有在这时候喂狗才合适;

3、当 计数器的值 从0x40变到0x3F的时候,将产生看门狗复位;当然在要产生复位的前一段时间,如果开启了提前唤醒中断,那么就会进入中断,在中断函数里,我们需要及时喂狗,否则会产生复位;

4、据网上资料介绍,在这个中断里面一般不进行喂狗,一般是系统去世前的“遗嘱”,比如存储重要的数据等。这个就需要根据个人需要设计。


下面择取部分程序,可以根据程序说明,计算出喂狗的时间,大家注意推敲,欢迎交流!

  1. /* 保存WWDG计数器的设置值,默认为最大值 */
  2. u8 WWDG_CNT = 0x7F;

  3. /*
  4. * 初始化窗口看门狗
  5. * tr    : T[6:0], 计数器值
  6. * wr    : W[6:0], 窗口值
  7. * fprer : 分频系数(WDGTB), 仅最低2位有效
  8. * Fwwdg = PCLK1 / (4096*2^fprer)
  9. */
  10. void WWDG_Init(u8 tr, u8 wr, u32 fprer)
  11. {  
  12.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);    // WWDG时钟使能
  13.    
  14.     WWDG_CNT = tr & WWDG_CNT;   // 初始化WWDG_CNT
  15.    
  16.     /* 看门狗节拍=(36MHz(PCLK1)/4096)/8 = 1098Hz */
  17.     /* 也就是说1秒钟计数器减1098下 */
  18.     /* 周期 T=1/1098 s = 0.91ms */
  19.     WWDG_SetPrescaler(fprer);   // 设置IWDG预分频值
  20.    
  21.     /* 窗口值用wr , 就是说计数器满是0x7F, 在减到wr之前喂狗了就算喂早了--会复位 */
  22.     /* wr值一定要大于0x40, 否则窗口值就不存在了, 因为计数器从 0x40减到0x3F会产生看门狗复位 */
  23.     WWDG_SetWindowValue(wr);    // 设置窗口值
  24.    
  25.     /* 看门狗使能, 并初始化定时器为0x7F 计数器减到0x3F时(T6位清零), 则产生一个复位*/
  26.     WWDG_Enable(WWDG_CNT);      // 使能看门狗, 设置 counter
  27.    
  28.     WWDG_ClearFlag();           // 清除提前唤醒中断标志位
  29.    
  30.     WWDG_NVIC_Init();           // 初始化窗口看门狗 NVIC
  31.    
  32.     /* 使能EW interrupt  这个在计数器减到0x40的时候产生一个"死前"中断,
  33.      * 当然也可以在这个中断里赶紧喂狗, 省得狗咬你(复位) */
  34.     WWDG_EnableIT();            // 开启窗口看门狗中断
  35. }



  36. /* WWDG 中断服务函数 */
  37. /*
  38. * 一般来说,这个"死前"中断里面不应该喂狗的,
  39. * 而是应该做系统临死前的一些工作, 例如保存重要数据之类的
  40. */
  41. void WWDG_IRQHandler(void)
  42. {   
  43.     WWDG_ClearFlag();           // 清除提前唤醒中断标志位
  44.    
  45.     LED1 = !LED1;               // LED1 状态翻转
  46.     printf("进入中断!\r\n");
  47. }



  48. int main(void)
  49. {
  50.     u8 tr, wr;
  51.    
  52.     delay_init();
  53.     NVIC_Configuration();   // 设置NVIC中断分组2:2位抢占优先级, 2位响应优先级
  54.     LED_Init();
  55.     KEY_Init();
  56.     uart_init(9600);
  57.    
  58.     LED0 = 0;
  59.     delay_ms(300);
  60.    
  61.     WWDG_Init(0x7F, 0x5F, WWDG_Prescaler_8);    // 计数器值为7f, 窗口寄存器值为5f, 分频数为8
  62.    
  63.     while(1)
  64.     {
  65.         LED0 = 1;
  66.         
  67.         wr=WWDG->CFR&0X7F;      // 窗口值
  68.       tr=WWDG->CR&0X7F;       // 计数器值


  69.         /* 注意tr和wr的比较,确定喂狗时间 */
  70.         if(tr<wr)   // 计数器值tr必须小于窗口值wr时才能喂狗,在之前喂狗则太早,会产生看门狗复位
  71.         {
  72.             WWDG_SetCounter(WWDG_CNT);
  73.             printf("正在喂狗!\r\n");
  74.         }
  75.                
  76.     }
  77.    
  78. }
复制代码

试验现象:DS0(红灯)先亮,再灭,DS1无变化。
试验现象说明:在规定的时间段及时的喂狗了,程序没有进入中断函数。

回复

使用道具 举报

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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