01. 独立看门狗简介
+ l, ^0 G: i( v% mSTM32F4 的独立看门狗由内部专门的 32Khz 低速时钟(LSI)驱动,即使主时钟发生故障,它也仍然有效。这里需要注意独立看门狗的时钟是一个内部RC时钟,所以并不是准确的32Khz,而是在 15~47Khz 之间的一个可变化的时钟,只是我们在估算的时候,以 32Khz 的频率来计算,看门狗对时间的要求不是很精确,所以,时钟有些偏差,都是可以接受的。! r# [1 I1 S: i2 A; x* c( @
) i1 y! f! f7 K% P02. 程序功能示例) o. ]1 _! x7 v7 D* [
在配置看门狗后,DS0 将常亮,如果 KEY_UP 按键按下,就喂狗,只要 KEY_UP 不停的按,看门狗就一直不会产生复位,保持 DS0 的常亮,一旦超过看门狗定溢出时间(Tout)还没按,那么将会导致程序重启,这将导致 DS0 熄灭一次。; W( k# J2 w" ? H$ N) m( i$ O
# S% Y" Z) W0 j- w9 Q9 z, J4 C+ X03. 硬件设计
; N8 w' V9 c) U2 _用到的硬件资源有:/ p+ W! A/ D( O
1) 指示灯 DS0! Z$ Z9 R3 P$ @( j6 l- |# g; W8 c& I
2) KEY_UP 按键7 O, V% F T1 a N% P7 [7 H& S( V+ w
3) 独立看门狗0 N+ q4 R1 l) { p
前面两个在之前都有介绍,而独立看门狗实验的核心是在 STM32F4 内部进行,并不需要外部电路。但是考虑到指示当前状态和喂狗等操作,我们需要 2 个 IO 口,一个用来输入喂狗信号,另外一个用来指示程序是否重启。喂狗我们采用板上的 KEY_UP 键来操作,而程序重启,则是通过 DS0 来指示的。9 ?1 v1 x9 @0 C6 k+ n
( G9 ^6 Y# B& a# S
04. 编程步骤6 @9 A0 }' W4 I4 U5 R$ c
4.1 取消寄存器写保护(向 IWDG_KR 写入 0X5555 )) [' N- E/ q3 G- {
- IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
复制代码 7 K- Y& N( v) L8 j5 s/ P+ Q
4.2 设置独立看门狗的预分频系数和重装载值- void IWDG_SetPrescaler(uint8_t IWDG_Prescaler); //设置 IWDG 预分频值) ^2 { v( b3 z9 b5 P7 [1 q
- void IWDG_SetReload(uint16_t Reload); //设置 IWDG 重装载值
复制代码
! @7 T# R5 R/ e& d& j1 x& R设置好看门狗的分频系数 prer 和重装载值就可以知道看门狗的喂狗时间(也就是看门狗溢出时间),该时间的计算方式为:
, P3 A7 ~3 V/ w0 i2 ]- H* e# S" w( I. t2 ?, b/ t; o
- Tout=((4×2^prer) ×rlr) /40
复制代码 & F/ G; h6 i0 ?$ @9 u# d
其中 Tout 为看门狗溢出时间(单位为 ms);prer 为看门狗时钟预分频值(IWDG_PR 值),范围为 0~7;rlr 为看门狗的重装载值(IWDG_RLR 的值);
, l* u+ E9 C# l5 ^0 H$ Y+ W( d# L" d e$ v* C$ X. E0 p& P
比如我们设定 prer 值为 4,rlr 值为 625,那么就可以得到 Tout=64×625/40=1000ms,这样,看门狗的溢出时间就是 1s,只要你在一秒钟之内,有一次写入 0XAAAA 到 IWDG_KR,就不会导致看门狗复位(当然写入多次也是可以的)。这里需要提醒大家的是,看门狗的时钟不是准确的 40Khz,所以在喂狗的时候,最好不要太晚了,否则,有可能发生看门狗复位。
6 F1 f" ]8 t( p$ M5 ~" r5 ~, {2 H% Z) j0 a9 c5 m" _0 F
4.3 重载计数值喂狗(向 IWDG_KR 写入 0XAAAA )
1 G. i$ Y* g, E4 ?( a& O! h% M9 f9 O; z
WDG_ReloadCounter(); //按照 IWDG 重装载寄存器的值重装载 IWDG 计数器1 ]+ |5 Z3 Z9 l H
: n5 G% Y8 c4 @6 b0 Q' R0 p2 Z) o
4.4 启动看门狗(向 向 IWDG_KR 写入 0XCCCC)2 \% t F+ z. a0 z' y
" S7 T' b6 ]& k: y
7 B [* R+ [: d, K9 Z# G3 z& }05. 程序示例
& s7 m; e# ]7 J% F+ liwdg.h文件- #ifndef __IWDG_H__
_- b; r5 L$ V1 H3 J+ Y - #define __IWDG_H__* Q& o1 M' `& M
- 8 ?4 n- b0 X# O6 W7 u
- #include "sys.h" ]3 z# h8 l7 L( [
) s5 j: U% h' @1 i- //看门狗初始化
. L& Q( s: Q6 g - void IWDG_Init(u8 prer, u16 value);. H" x3 B- z; X) I) J! J
6 f- v) ~0 Z9 ^6 x- ?* s" K- //喂狗! P: I+ {/ i' V7 L' M
- void IWDG_Feed(void);
% D9 _3 \" b* J" _1 {5 w; h$ P - : I" D2 }& d& |- x% J
- #endif/*__IWDG_H__*/
复制代码 ( z* K5 q; [" @7 u$ l: g
iwdg.c文件' A# E; J& H8 H- e) y3 a4 X
8 G3 Q2 G8 L z6 W& _- #include "iwdg.h"
' z- h0 J# t* b. B$ k" f2 P - $ X1 a2 K7 T+ Q
0 M" T4 N0 n. f- //看门狗初始化
# |5 k; s3 t- f$ @" w0 ] - void IWDG_Init(u8 prer, u16 value)
; n1 C/ Y% E. C. [; U - {
! o) i. U: W' ~' H2 O O0 A - //取消写访问保护
( N2 T$ S$ N9 }: X3 u: ~ - IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);* T5 N' ?# f: V% v7 J, Z9 S4 x
-
) S. ]9 v* m/ i! x: A# I - //设置预分频+ Y" _9 o1 x" A1 r0 _1 t
- IWDG_SetPrescaler(prer);5 e* c: Z% I* P0 m/ G+ h C
- 6 C% c& I2 v- r% O3 r- ]6 ~
- //设置IWDG装载值
& d* E) x" v$ l4 q3 V, K6 s - IWDG_SetReload(value);* K" ?/ m7 H! K8 a3 i" |2 u0 n
-
, ]* d# |1 k% P5 n# K - //重新装载6 F; w# ?& Y8 a+ v) Y# ~
- IWDG_ReloadCounter();
: W! x9 e. H3 H6 }: i7 h - 9 d9 r! A& r6 p: A& l
- //使能看门狗 n. k$ E# x6 L: F& S
- IWDG_Enable();
; I* t. m* z+ W0 U. |$ _ -
J, M2 [4 K( X0 L# I# f - }
8 r# p6 D( a+ I
. |9 q1 _* g$ l+ G3 t- //喂狗: E, N9 i* V6 p& N. j* ]
- void IWDG_Feed(void)0 H3 l# d/ }3 a
- {
6 N: s1 \. z; x U- T7 Q/ D! @) u - //重新装载
; }+ }. W, }2 X3 z, x' G5 d o - IWDG_ReloadCounter();
1 v7 j, [* ~- L% R3 o: v8 e- w4 }" f - }
复制代码 ! {0 k) J$ c; F2 R' h/ k2 S6 v
main.c文件 Q* Y' |4 r, n: \1 W
1 G6 k5 _+ [. X3 K$ W3 u) a' }9 ~
- #include "sys.h"! m! v1 c- s2 Z% ~8 S6 Z( K$ n
- #include "delay.h"
?$ \0 I: {. p3 X' X - #include "usart.h"5 m0 \$ E% ~" f
- #include "led.h"
3 a; d& l9 d/ |& Q; W - #include "beep.h"' Q; i# k/ ?9 `, n y
- #include "key.h"5 Y0 ?4 Y7 T I& w
- #include "exti.h"
- u& P1 P' [" J - #include "iwdg.h"; j0 w5 b6 Y. E0 e2 C: j% C
- - N$ m) k# S% N& f' E
- int main(void)
* s) J, |# l, y& p7 P$ D3 z) u2 ` - {
7 I" [6 W- S3 t4 {% ]8 ^( H - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
' A5 s6 a5 A8 _$ _, R+ R -
! G7 S5 Q- a+ [& D - delay_init(168);
% T) @1 x4 `& I3 u - LED_Init();
$ \; Q, \+ h$ H% ?8 X - KEY_Init();
8 O, R/ A; _3 B& m - uart_init(115200);
t' C3 j" u a: s - " K' ^" v$ ]1 A+ j4 X) q
- LED2 = 0;
# ?; S! t3 t6 ?+ l$ g - 3 A7 e0 d& z; }' r
- delay_ms(100);. x) ]7 J9 m7 S2 x" i& u9 F
-
! ?# X, N; e4 |" f$ X1 c - //大约6秒) w9 P# l8 g$ f, [5 E0 S
- IWDG_Init(6, 500);
' r o0 M, ~( U( \" j. v9 R - 7 ~( [# q8 y$ X/ x) v4 X
- printf("程序初始化OK\r\n");3 s# ~: T, J5 C' d7 z6 X w
-
, f) l* o& `& T. l5 C* ]3 T - while(1)
3 e/ P1 s u! _. h3 d - {+ M5 X/ r5 K& z C. c
- if (Key_Scan() == WK_UP_PRESS), P) R* q7 i- b" x2 W6 J! r1 z3 f
- {6 g) q4 L# ]4 @% B3 J/ {) S7 D
- //喂狗
' W# A* J* z6 k8 W S - IWDG_Feed();# ]/ ?, {: V6 I
- printf("喂狗\r\n");; I$ `+ V3 {, Y* a2 [5 H
- }0 x+ e' d# W! L7 Y2 |
- 9 s, \3 ]! D) E$ I7 Z, e
- printf("while do work \r\n"); ( Y1 A+ X' t6 G) C$ w+ Q# o
- delay_ms(1000);
7 w' G; R/ h. n; j+ s+ T - }
$ a9 h# B1 ^3 x1 \. F" o: ^% j: M - }
复制代码
1 [' h+ ]- |/ R
! q/ T; e# z# D' X, v4 w: {, b. L
|