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

用STM32 作两只看门狗

[复制链接]
STMCU小助手 发布时间:2023-2-26 16:16
STM32 独立看门狗,
由专门的低速时钟 (LSI) 驱动,即便是主时钟发生故障它仍能够有效,所以此狗狗可以工作在与主时钟无关的要求下,或者待机模块下等,所以它叫独立看门狗,注意一旦开启此看门狗则只能由 MCU 复位后才清除,让它不再工作。
它的时钟是一个内部 RC 时钟,它会在 30KHZ 到 60KHZ 之间变化,并非是精确的 40KHZ,而只是一般计算时取 40KHZ。" h$ |" U  g! M

7 r/ l& y9 A  C1 J
独立看门狗需设置四个寄存器如下:% ~3 y( W% q2 {9 ?! K$ I) M" K
其中,
预分频寄存器 (IWDG_PR),最低三位 PR [2:0](Prescaler divider) 有效,可设置有 8 种不同的计数器时钟预分频因子。
重装载寄存器 (IWDG_RLR) 低 12 位 RL [11:0]: 看门狗计数器重装载值 (Watchdog counter reload value) 有效,用来设置计数器的重装载值。
注意要设置以上两个寄存器的值需满足两个条件,详见如下:
键寄存器 (IWDG_KR),用来控制去除 IWDG_PR 和 IWDG_RLR 写保护功能以便正常写值,向此寄存器写入 0x5555 则暂时去除 IWDG_PR 和 IWDG_RLR 的写保护功能才可向两个寄存器中写值。当向此寄存器写入 0xAAAA 则 IWDG_RLR 的值会重装载,防止 MCU 复位,向入 0xCCCC 是开启狗立看门狗动作。

: Q: i2 b3 |& E5 D5 X; [) ~
状态寄存器 (IWDG_SR) 最低两位有效 RVU: 看门狗计数器重装载值更新 (Watchdog counter reload value update) 标识位和 PVU: 看门狗预分频值更新 (Watchdog prescaler value update) 标识位,分别用来指示此时是否可向 IWDG_RLR  和 IWDG_PR 写值,此寄存器由硬件置 1 与清 0,只有当为 0 时才可向上面两个寄存器写值。
它的初始化过程大致如下 :  
  1. //时间计算(大概):Tout=((4*2^prer)*rlr)/40 (ms)
    . w9 ?- D. o9 n1 l
  2. void IWDG_Init(u8 prer,u16 rlr)
    + N6 W6 W* |# ?
  3. {      
    / X% o0 Q% i* U" ]7 P
  4.         IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
    ! A7 M" f# y' K) {
  5.          IWDG_SetPrescaler(prer);   
    / B; D, ]2 g+ B- F$ B! ~/ G
  6.          IWDG_SetReload(rlr); - \7 R/ ?7 B' D0 n. Z/ [
  7.          IWDG_ReloadCounter();      1 W$ J) b, k8 a! F% i
  8.          IWDG_Enable(); 1 L& `1 r$ b  b
  9. }
复制代码
) E' o2 X' o; }6 G9 N
喂狗可通过调用如下函数进行:
  1. IWDG_ReloadCounter();//reload
复制代码

! N- ~8 a* `. p5 S' P8 r7 f
以上参考正点原子相关代码,朋友们可以跳到库函数代码中自己研究下,控制比较简单,不再赘述。另外要注意不要使用硬件时钟中断喂狗,因为硬件时钟中断一般都有较高优先级且独立于主控程序,这样有时会出现主控程序虽然跑飞了,但仍能够正常喂狗的现象。
3 w! d, x5 S5 z% j' Y6 v# i& @) v
独立看门狗能够在一定程度上监控着程序正常运行,然而我认为更加强大,应用更灵活及更能保证程序稳定运行的还属窗口看门狗,虽然它开始时不太好理解。
, E5 n5 e& _3 M0 _2 ]
STM32 窗口看门狗
共三个寄存器,如下图:

4 r+ S8 O, w( H# R$ L# D+ a' g( H
看似简单,但设置及应用起来有不少玄机。
控制寄存器 (WWDG_CR) 中的值必须在 0xFF 与 0xC0 之间, 因为它的第 0 至第 6 位为递减计数器 CNT,在它的第 6 位变为 0 时将产生复位,所以在初始化时需要为 1,第 7 位 WDGA 是用来设置启动或禁止窗口看门狗的,当为 1 进才会启动窗口看门狗,所以第 6 和第 7 位都需为 1,即 WWDG_CR 的值需要大于等于 0xC0 。
配置寄存器 (WWDG_CFR) 第 0 至第 6 位 是设置窗口边界值用的,只有当递减计数器 CNT 的值小于边界值时才可以喂狗,过早不行,狗还不饿,撑死了。并且 7 位递减计数器 CNT 减少到 0x3F 时即 T6 位变为 0,此时 MCU 也会复位,过晚了,狗饿死了。所以必须在指定的时间范围喂狗,过早或过晚都将产生复位,而这样设计可以减少软件跑飞了却仍能够歪打正着地喂狗的发生概率。
状态寄存器 (WWDG_CFR) 只用到了第 0 位,EWIF (Early wakeup interrupt flag ) 是提前唤醒中断标识,当递减计数器 CNT 的值到达 0X40 (若再减少一次则 T6 位变为 0,产生复位) 时此位由硬件置 1,且需用软件清 0,注意无论中断是否使能此位都会被硬件置 1。而提前唤醒中断使能设置是在配置寄存器 (WWDG_CFR) 第 9 位 EWI (Early wakeup interrupt),此位需由软件置 1,则会在当递减计数器 CNT 的值到达 0X40 时产生中断,并且与 EWIF 不同,此位是由硬件清 0。
另外控制寄存器 (WWDG_CR) 中第 7 位 WDGA (Activation bit) 激活位,需用软件来置 1,以启动窗口看门狗,并且一旦启动后,只能在复位或重启后由硬件来清 0。
配置寄存器 (WWDG_CFR) 的第 8 位和第 7 位 WDGTB [1:0] 用来设置时基 (Timer base) 预分频数。5 f+ V2 f* S4 x; o, j  B9 D% `/ s
以上描述可参考下图以更清晰的理解:
窗口看门狗应用时还要注意算准最小与最大喂狗时间,以便正确地喂狗,如下:
在 PCLK1 频率为 36MHz 时,则
上窗口时间:T_min = 4096 * (2^WDGTB)*(WWDG_CR [6:0] - WWDG_CFR [6:0])/36 (us)
下窗口时间: T_max = 4096 * (2^WDGTB)*(WWDG_CR [6:0] - 0x40)/36 (us) 。
' L  X! N% j8 h$ o
喂狗动作需在这段时间之间进行,而喂狗动作为向控制寄存器 (WWDG_CR) 中写值,值的范围上文已经说过。
窗口看门狗中断函数 void WWDG_IRQHandler (void);是用来做什么的呢。窗口看门狗中断函数是在递减计数器减少到 0x40 是被调用,因为它本身计数就比较慢,所以离数到 0x3F 复位还有一段时间,我认为这样设计是为 MCU 复位之前留下一点时间,能够使工程设计人员根据需要在中断函数保存一些重要的数据,这样在复位后 MCU 可知道系统因异常复位的某此状态,以使系统有更高稳定性。
并且我觉得在窗口看门狗中断函数中喂狗没有什么意义,程序本来已经不按正常运行了,还在中断函数中喂狗防止复位只会错上加错,不好好利用它干点正事, 更是浪费资源。
这点上我个人认为不要被点原子示例代码误导哦,但其还是有部分借鉴意义的,以下为初始化相关代码:
. x7 M0 @: Z, L& R
  1.   //窗口看门狗中断服务设置程序
    9 b1 E' w5 Q: a. p# ]/ a% }
  2.     void WWDG_NVIC_Init()
    8 z% j$ @& T4 V0 W6 f) C
  3.     {! e) X4 S: _* \. U8 q8 ^; q$ N
  4.       NVIC_InitTypeDef NVIC_InitStructure;
    : o" E& B8 u3 ?; z) Y$ _/ Z
  5.       NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);      # O/ u- ]1 Z8 A# a: b. q2 J
  6.       NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;       //WWDG 中断/ }) }# `" W. ]3 [
  7.       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占2 子优先级3 组2
    7 _) V! ]0 k5 f5 K8 J
  8.       NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;    //抢占2,子优先级3,组2
    * u5 v) {5 `( d, Z( h& Y
  9.       NVIC_Init(&NVIC_InitStructure);                       //NVIC 初始化
    % d1 b5 _8 E1 `7 ~1 I
  10.     }
复制代码
  1. //保存WWDG 计数器的设置值,默认为最大.
    . o7 g3 h7 r) f1 U0 v  H1 U$ |
  2. u8 WWDG_CNT=0x7f;
复制代码
  1. //初始化窗口看门狗
    : J: C2 `& c" t$ J- D5 ^, s" d: p0 c
  2.     //tr  :T[6:0],计数器值
    3 j9 y- Z5 k% v' I9 h) v
  3.     //wr   :W[6:0],窗口值
    4 j7 M2 g: P0 _' X& @
  4.     //fprer:分频系数(WDGTB ),仅最低2 位有效
      G* V1 j: p% d' x1 s8 B1 `2 d$ ?
  5.     //Fwwdg=PCLK1/(4096*2^fprer).
    3 o3 F% v. \2 q
  6.     void WWDG_Init(u8 tr,u8 wr,u32 fprer), b+ R' q# Q6 @
  7.     {) v7 p% A3 k3 u5 [% C( }
  8.       RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); // WWDG 时钟使能0 W1 g0 ]( o0 t# h6 m. H
  9.       WWDG_CNT=tr&WWDG_CNT;      //初始化WWDG_CNT.
    6 G+ H& P+ J2 ?. \& j% I
  10.       WWDG_SetPrescaler(fprer);        //设置IWDG 预分频值. P4 a  ^0 a: D" T" c' o0 V
  11.       WWDG_SetWindowValue(wr);       //设置窗口值$ k8 [; |; \1 u/ m5 [: Y
  12.       WWDG_Enable(WWDG_CNT);       //使能看门狗,设置counter
    ! D, a, y5 [' c
  13.       WWDG_ClearFlag();               //清除提前唤醒中断标志位 (注:若没有此句则会在初始化后先进入中断一次)
    8 q' T3 S9 W% F" P- C2 s! H; d
  14.       WWDG_NVIC_Init();               //初始化窗口看门狗NVIC+ C9 c% s. g! k, l% T! k
  15.       WWDG_EnableIT();                //开启窗口看门狗中断
    . j* ^: m- d: X4 V
  16. }
复制代码

2 s0 O+ S7 e7 ?# X) ~- Q4 p- O4 |转载自:以太快跑
# ]) R2 X, ?' J; L- m/ F8 Y& l5 m7 o) [9 O
赞 收藏 评论0 发布时间:2023-2-26 16:16

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版