一、窗口看门狗由从APB1时钟分频后得到时钟驱动。3 \2 O' d- ^) \) z W
* f, C4 J$ v/ [: d o: v 通过可配置的时间窗口来检测应用程序非正常的过迟或过早操作。
( l& k% C3 L3 \- ` g) U+ ^% m h, F% f. p5 P
窗口看门狗最适合那些要求看门狗在精确计时窗口起作用的程序。+ s) s1 v/ N. A3 T- r* T/ d" ]
5 x3 ~, \ u# f8 B7 E
二、什么是窗口看门狗?! U* f7 n1 B! f5 H8 m" m+ U/ Y9 v
" C8 [: v/ l j窗口就是因为其喂狗时间是一个有上下限的范围内(窗口),你可以通过设定相关寄存器,设定其上限时间(下限固定)。喂狗的时间不能过早也不能过晚。
8 D; l2 {& o0 A; V% H" X& a
6 v1 }. x% h5 z1 H而独立看门狗限制喂狗时间在0-x内,x由相关寄存器决定。喂狗的时间不能过晚+ T" h) ~- X1 p/ _6 x
2 Y9 p- x' E# q; S6 A3 `三、窗口看门狗的好处# F! T' O8 j3 h+ M1 _9 @
5 U8 B( Z- G9 ]" O
对于一般的看门狗,因为是在复位前的任意时刻刷新看门狗,但有可能程序跑乱了又跑回到正常的地方,或跑乱的程序正好执行了刷新看门狗操作,这样的情况下就检测不出来了;
; X/ U3 Q( X. C+ `9 D. e( L, X- X
如果使用窗口看门狗,程序员可以根据程序正常执行的时间设置刷新看门狗的一个时间窗口,保证不会提前也不会滞后刷新看门狗,这样可以检测出程序没有按照正常的路径运行非正常地跳过了某些程序段的情况。
6 J9 e) _7 h5 f) N( b7 r
+ l4 x& t! J# K9 |3 L四、窗口看门狗工作示意图及框图
0 i* O) b, x9 @' X9 m3 h$ h) G
0 }1 h# a, b- o/ Y上窗口值W[6:0]必须大于下窗口值0x40。否则就无窗口了5 U) U1 q% ?6 f6 u8 H
8 m6 d p; @9 Q# G
" p/ z3 N$ f2 c: G9 s/ F: M1 t! i9 o0 y2 |* _! A
工作示意图
- M( ] h1 A, K
- c3 L# _$ o/ V% k
) c& v# R& ?3 ?! d' l
8 A1 e8 I9 _0 s4 K: E五、产生复位的几种条件7 ~- `5 Y; r* ?) T6 }" i! |& W
9 k4 e1 z# M' ^- C. J$ Z& T; R1 h. j
STM32F的窗口看门狗中有一个7位的递减计数器T[6:0],它会在出现下述2种情况之一时产生看门狗复位:
, _& Q$ \( @- C2 P, D- E( v- {2 C6 O- R( k5 d2 T1 A
①当喂狗的时候如果计数器的值大于某一设定数值W[6:0]时,此设定数值在WWDG_CFR寄存器定义。" J3 j N" a3 X# Y* k, e# ]
5 h# A2 o; d! T# n2 u②当计数器的数值从0x40减到0x3F时【T6位跳变到0】。6 k: w+ M4 d0 W6 C' s
+ h0 A0 }" G* l+ m5 ~. Z4 q$ U
如果启动了看门狗并且允许中断,当递减计数器等于0x40时产生早期唤醒中断(EWI),它可以用于喂狗以避免WWDG复位。
8 F9 b' u8 r' b8 ?1 X3 X1 W/ M# \0 L7 p3 _% ~4 I
六、窗口看门狗配置过程
7 s# e6 A; k( `
8 a* y" a, K' _4 _/ ~! f( e& V- //①使能看门狗时钟:4 r. X% p& j( Q' U, I* z8 Y( K" i& v
* X/ Y( s9 M4 l- U! P' B- RCC_APB1PeriphClockCmd();
6 S! W J0 E- _% v& q - : @6 u$ g8 i: o7 ~6 {5 H
- //② 设置分频系数:
, ?: L) @( [* Y - 3 h4 N& P/ u. V* ~+ B o
- WWDG_SetPrescaler();* v. V: `& l% m6 |& Q
- @8 h) W) Y, r) [
- //③设置上窗口值:
5 a( a, T8 g* e6 P - . T% Y1 S/ n2 Q' S, x0 |
- WWDG_SetWindowValue();
^1 R( ?/ o) ?' X! u
+ P, i ?1 j; w: ]. ^- //④开启提前唤醒中断并分组(可选):# w7 R6 B& K g* ~9 z$ w
- 7 t; k' j3 k- B9 g
- WWDG_EnableIT();
# G4 R' N% B, D1 v - # L9 k+ Z7 `- F
- NVIC_Init();; @) {# y) r I9 H: S0 f0 q' V F4 \
! w9 ~1 P6 ]7 o" v$ h Q/ P- //⑤使能看门狗:5 t3 Q ^; M, n: e0 G3 b- u% D
/ y. s7 V7 Y2 _; c- WWDG_Enable();
- ]& I/ y$ Z1 N& I- H# S+ T
% ~8 B! B a* |2 [1 V: i6 q3 q% R- //⑥喂狗:: ]7 Z$ D, B }# @) b& z+ w
6 }7 Y, C4 |! }. H- WWDG_SetCounter();' W' m" L1 D0 y# h& W7 X4 B0 _1 _
- ' ~2 r' ?- t3 x* A l
- //⑦编写中断服务函数" c. f$ {9 ^2 n' m& ]
% R+ ^3 f/ f+ B- WWDG_IRQHandler();
, { U& V% H9 t j/ w) O2 U
复制代码
: D6 i+ C( D- n, e代码如下:9 d5 @$ [/ s# H" F
! n; ~$ S. G" E3 _6 ]8 n3 z
- void init_wwdg(void)
- P" w; K, `8 J& U; G R - {9 m1 u) \6 I i" X$ I i: C
- NVIC_InitTypeDef NVIC_InitStructure;
% H* j* K' g3 i" l6 R5 u7 |
% k; ?& `* N) s+ a( a* ~- //使能wwdg时钟# r5 N5 D% T3 K, {& b4 O
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);8 I! I* b& V5 e; W( \
5 ~7 Q1 C* V: y7 F ]$ G7 r- // WWDG_CNT=0x7F&WWDG_CNT; //初始化WWDG_CNT.
6 l5 I- t5 z. {0 O: W - _0 t$ H7 }% e3 s9 R. }8 w4 G
- 2 r" t, O+ M+ z, U; X# E# f! W
- //设置看门狗时钟 1281Hz = (PCLK1 (42MHz)/4096)/8 = 1281 Hz (~780 us)
, b: v, [) U( A+ | {7 a6 y: n - //指定WWDG预分频器
2 _, o: g( D. b, ~ ^0 {/ a5 i - WWDG_SetPrescaler(WWDG_Prescaler_8);//Prescaler:计数器时钟
( P$ Y- R2 h# L7 ^. M
" T' l6 H) E; z9 `0 R+ ^- //设置窗口值为80; WWDG计数器只有在计数器时才能刷新低于80(大于64),否则会产生复位
* e0 r2 C7 Z5 s - WWDG_SetWindowValue(0x60);& k9 B' b1 P9 u' b5 X% U+ T4 \
- % S- _; q. J, G. ~! c, `
- //设置重载计数值,也就是喂狗
" ~* I) p2 j7 Q4 }( [$ V/ V; a W - WWDG_Enable(0x7f);0 e# F9 @4 Z2 K# R9 ^
9 y& I8 ]- C' a0 Y- ^- ! D3 L. O2 \6 C+ Q6 w, w- X
- // 初始化中断5 g: M* ~4 R1 D( H3 `8 Y
- NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn; // EXTI0的中断向量号5 f' m' l9 F6 i7 ?0 P! _/ g
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; // 抢占优先级
( C. K1 b ]" G% _3 l6 B; s - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 响应优先级
$ D W! V" n4 J - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能中断; _( c) L# t' W% _
- NVIC_Init(&NVIC_InitStructure);4 H1 K, ?: [. `& A `2 T' S
- 3 R; J8 \( m S: U @
- // 清空提前唤醒中断的标志位+ \6 H7 v2 K1 V9 |" m1 i
- WWDG_ClearFlag();
) k. `' K7 n7 z, W1 I8 w - 3 t# T9 I' ~0 {! S8 |* v& h8 ?) b* t
- // 使能提前唤醒中断
* b0 b# b$ f( `) K - WWDG_EnableIT();
) e4 u+ ] v( H* ?' d' I - }2 j% w4 d2 E2 g' N& J
- " w8 w5 J4 s. c! s4 ~
, K- I4 A# G& z- //当递减计数器递减到0x40时,触发中断函数,进行喂狗
c# n. L' o6 I' I5 M - void WWDG_IRQHandler(void)
2 d2 ]! r+ }. O; z6 o5 B0 ? - {
- S/ t% W4 T% q5 c* w; {% C. R - if(WWDG_GetFlagStatus() == SET)
( g( Y9 \) t4 H* E6 _ - {
* |+ F+ W" M, z4 b/ ^7 J3 _0 R' T - // 喂狗
; a! Z# d) R4 S% U; i: x) h - WWDG_SetCounter(127);- f5 d4 N7 Y, k9 |' e: K
- //WWDG_SetCounter(WWDG_CNT);* b" @1 E3 }9 C& U I7 r1 l
- //清空提前唤醒中断的标志位
5 A, h/ y6 ?( D! ~% n+ {: b - WWDG_ClearFlag(); x$ e. d3 M+ K4 g) n
- }
7 I: O$ \* v$ R( {' P$ i9 N - } O: m: t2 B' U( U
复制代码 * Y( L. K" J# ?: r
6 m4 z& O0 W7 b) w5 q- q8 c9 Y! h5 k" Q. n
. Z3 f% g' `- ^
% \1 B4 ~5 K0 p& ^- y; |. ]- A7 o D
8 d" N5 i( d( `+ K' Z |