01. 独立看门狗简介3 A6 J8 C4 l# }) F, o2 u6 Z, r' L% R% R
STM32F4 的独立看门狗由内部专门的 32Khz 低速时钟(LSI)驱动,即使主时钟发生故障,它也仍然有效。这里需要注意独立看门狗的时钟是一个内部RC时钟,所以并不是准确的32Khz,而是在 15~47Khz 之间的一个可变化的时钟,只是我们在估算的时候,以 32Khz 的频率来计算,看门狗对时间的要求不是很精确,所以,时钟有些偏差,都是可以接受的。
5 ^8 n( q& k* w( g
0 X/ T" w" I( i# i02. 程序功能示例( k6 x! I; ~# c2 @- V
在配置看门狗后,DS0 将常亮,如果 KEY_UP 按键按下,就喂狗,只要 KEY_UP 不停的按,看门狗就一直不会产生复位,保持 DS0 的常亮,一旦超过看门狗定溢出时间(Tout)还没按,那么将会导致程序重启,这将导致 DS0 熄灭一次。# l, ^# x& a" K
9 L2 b5 B y/ P: K
03. 硬件设计/ [0 R$ I5 w, z8 T5 ^+ E! v L. N( Y
用到的硬件资源有:8 l. C+ v, {& j5 R) k: n# s6 l
1) 指示灯 DS0
: Z) R1 S# Q; u" z2) KEY_UP 按键) O& j' l( M! w- `% `9 Q
3) 独立看门狗
8 n5 h# a; t# D" g; R前面两个在之前都有介绍,而独立看门狗实验的核心是在 STM32F4 内部进行,并不需要外部电路。但是考虑到指示当前状态和喂狗等操作,我们需要 2 个 IO 口,一个用来输入喂狗信号,另外一个用来指示程序是否重启。喂狗我们采用板上的 KEY_UP 键来操作,而程序重启,则是通过 DS0 来指示的。
$ D; X! z" P2 a( |; ^
6 z' K! c6 s9 e; V04. 编程步骤
7 P- M: ^- F) j5 k8 f) T; ^! D* o4.1 取消寄存器写保护(向 IWDG_KR 写入 0X5555 )
8 T3 G+ [+ v* j, C1 k2 a- IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
复制代码 " {/ M0 V% g/ h$ [( n+ X" K" x9 x9 |
4.2 设置独立看门狗的预分频系数和重装载值- void IWDG_SetPrescaler(uint8_t IWDG_Prescaler); //设置 IWDG 预分频值, V/ v% l9 X: R
- void IWDG_SetReload(uint16_t Reload); //设置 IWDG 重装载值
复制代码
4 t1 s* q3 d3 d3 r% h设置好看门狗的分频系数 prer 和重装载值就可以知道看门狗的喂狗时间(也就是看门狗溢出时间),该时间的计算方式为:+ k0 b5 s( I6 E! e7 V3 g4 ?0 y
( h1 S6 ~. a; N r- Tout=((4×2^prer) ×rlr) /40
复制代码 4 w7 N' b5 p' K. G- f
其中 Tout 为看门狗溢出时间(单位为 ms);prer 为看门狗时钟预分频值(IWDG_PR 值),范围为 0~7;rlr 为看门狗的重装载值(IWDG_RLR 的值);: h) H2 ~! L ~7 p# @+ b
e6 R0 a( z% k; u比如我们设定 prer 值为 4,rlr 值为 625,那么就可以得到 Tout=64×625/40=1000ms,这样,看门狗的溢出时间就是 1s,只要你在一秒钟之内,有一次写入 0XAAAA 到 IWDG_KR,就不会导致看门狗复位(当然写入多次也是可以的)。这里需要提醒大家的是,看门狗的时钟不是准确的 40Khz,所以在喂狗的时候,最好不要太晚了,否则,有可能发生看门狗复位。
) D2 f7 J& S/ x" O1 @
4 k. s- ]0 b* x8 d$ d8 T4.3 重载计数值喂狗(向 IWDG_KR 写入 0XAAAA )
" ?: g8 g) n- V2 N; Z; e8 N, V! V- F }
WDG_ReloadCounter(); //按照 IWDG 重装载寄存器的值重装载 IWDG 计数器$ r0 K4 D. ?. G4 v% P
8 A" P8 l5 a( G' L
4.4 启动看门狗(向 向 IWDG_KR 写入 0XCCCC). s( m- c9 G" `& R4 d( c+ j( ]* B
( J# H( f1 H" Y9 i3 a
( x( o2 g/ r' t% `& d05. 程序示例' Z; F( b% |2 Q) W8 I
iwdg.h文件- #ifndef __IWDG_H__
, j% v3 D0 G" W - #define __IWDG_H__' Z; X2 I u4 S- ~+ i+ B* K
) x% ^* N1 h6 P$ x0 T- #include "sys.h"& N/ ~7 M/ X- F6 {) W
+ K! E i2 u! ]! T4 R# c8 y- //看门狗初始化
. {* ?. B: }; s* a! k6 o+ F+ b C - void IWDG_Init(u8 prer, u16 value);
/ [1 c( k1 S7 w
$ l8 L- K/ t' S2 i- //喂狗, @* ~! B. X# H& }* @
- void IWDG_Feed(void);
( m$ Q/ F2 U+ ?0 n
E7 m: ]1 _4 z6 P' v, M- #endif/*__IWDG_H__*/
复制代码
9 e; w. o9 }) l9 piwdg.c文件
7 e: J; K7 Q" l4 V) P0 M) P* ^" g, A! `9 R/ c0 X
- #include "iwdg.h"( x+ A' Q+ j6 Z
- : ^6 Q) W+ t! H' O) B* C
- ! U: L7 ~# ]4 V8 y) H" |
- //看门狗初始化
# Y. y5 t$ `) c' y7 K - void IWDG_Init(u8 prer, u16 value)
B: _7 p* \* F* T% ?8 X6 b/ Y. @ - {
3 `* f/ W' }" x. R - //取消写访问保护. v- @9 w) H5 B) q/ x3 q
- IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
4 ~2 w$ J ]) E. v4 H* V -
0 H' G$ p( q6 } - //设置预分频
, B' g! t% l# _: h) U - IWDG_SetPrescaler(prer);
7 A, P, c& u/ ^0 Z" u -
+ O4 Y" A2 I3 e" e - //设置IWDG装载值+ E( g6 `4 [$ H$ c3 h: y- Q
- IWDG_SetReload(value);- N5 T$ X( D$ o- W
- ; B, {* \' Y" T
- //重新装载
4 f( \6 n5 I6 m# F - IWDG_ReloadCounter();3 T# I9 T# N# c! f2 m1 C
- 0 j/ j, Q8 g* t( l X( V/ T9 d- V
- //使能看门狗
\+ T: i" d2 \9 b) A4 B# R0 Q - IWDG_Enable();
) e9 Z* P: t! Q7 _2 v$ K, _ -
) Y3 d! U. q# B8 _ - }5 C0 m! T- R9 X8 a
5 W$ ^( J3 e0 s/ s! W1 B- //喂狗
5 O4 \5 l: ?: t& f, D& g - void IWDG_Feed(void)
) d; G# u( V% i' G+ g$ I/ d - { 2 m& C$ I2 f6 V4 v
- //重新装载* k3 P- O& f' F7 ^! r3 h
- IWDG_ReloadCounter();. P, n# ^* B* I. f
- }
复制代码 9 N4 |9 h+ r4 D, a* s: z
main.c文件
) @; _9 U- J! s8 n4 O" B$ h/ e7 s' Q& S
- #include "sys.h"
$ W2 ^) u( ?/ k, |1 d3 e$ x& G - #include "delay.h"
9 r9 J, @3 p% y5 T. ~ - #include "usart.h"
: E; m* ^* W2 N5 {3 ?$ [7 ?+ t - #include "led.h"- k7 a6 m+ L2 ~( p& c
- #include "beep.h"
& q2 q P+ d/ ]" G1 g2 q - #include "key.h"* U* A! V* B9 }* |! T
- #include "exti.h"
- D; u0 n" c% X% P# y0 H/ N4 X0 I - #include "iwdg.h"
7 t, P6 V2 `- x& Y3 {' m* E, k
% \6 x |1 E; }3 h, b6 W: K% c- p- int main(void) x5 J. N0 ?5 K# ?0 @1 A/ B: W
- {
9 P d7 l$ P d - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
7 V4 o: |; R* F' D" @+ H2 X0 \) A - 0 H; N& S0 o) j! R! M& M
- delay_init(168);
( @# K% g% c1 C' I/ a - LED_Init();* i3 U& w) i5 n" n
- KEY_Init();0 {& ~+ x4 H, }3 f
- uart_init(115200);$ J$ S# c. j/ ?" f8 R- @; x+ K. L
-
, q, C' W! Y! N T. p - LED2 = 0;( z. ]# }3 h1 S/ N2 Q
- , `8 D8 z$ T& J4 I6 L; u
- delay_ms(100);! |7 k( v) g0 z: m; O/ G# ?0 {
-
% R: n: W* X+ h- S6 D; Z, X - //大约6秒
8 c3 x0 C. C* p+ L5 r) d- [' f - IWDG_Init(6, 500);
' X/ g- Y& S: k% Z/ _6 X -
# t0 Q% E8 l8 k0 g - printf("程序初始化OK\r\n");
: c# R6 k; }# X+ g5 o -
; g4 |; C0 s" F; T - while(1)3 W# y. f7 k4 D7 J' a3 L/ g
- {1 [5 ~4 _6 a4 p+ I7 C" L
- if (Key_Scan() == WK_UP_PRESS)5 _* q. W+ \7 S8 m8 ]! ~
- {# A( Q& A' D5 j2 m% t
- //喂狗& V9 y6 [7 F' K8 X
- IWDG_Feed();
3 p+ l8 I2 z7 M3 g, d5 ? - printf("喂狗\r\n");3 g9 ?, ?! e+ e j# {5 x
- }
- V/ U5 \5 l0 a/ a$ U" t -
- W% \6 O* W$ k - printf("while do work \r\n");
% P; Q' D( p! V' C+ \9 x - delay_ms(1000);
; E! c n+ b9 d( u/ \; s - }
. O+ n3 r% l" M4 i4 v5 G - }
复制代码
, Z) T9 J& Z% ?' H" q. ~, R) A
4 S% U h* v3 \- C3 Q6 h3 d
; E5 G# G+ u+ S. l1 A s: y( c \ |