【前言】本帖只贴出了函数所需的部分源码,所贴源码并不完整!: [) }4 a4 G2 a/ l" B0 Y
* L# j) A% S7 ^1 g1 C固件库提供的 “检查指定RCC标志位设置与否” 的函数在源文件 “stm32f10x_rcc.c” 里的原型如下:
' p, B1 g& y" t& L& p0 c- /**! ?) [- j: S7 W' W5 i9 I: M) o& R
- * @brief Checks whether the specified RCC flag is set or not.: X: E+ t9 c! `( w% w5 i* q0 @ n
- * @param RCC_FLAG: specifies the flag to check.9 R% [0 k4 j G: }; b& [0 ]8 D( C
- *
S9 ~! z1 _* D7 B4 Q4 j - * For @b other_STM32_devices, this parameter can be one of the following values:
4 y7 P3 D) m1 h) q4 q$ K# K/ p: M - * @arg RCC_FLAG_HSIRDY: HSI oscillator clock ready
& \ T$ o) e7 d6 T# N( p! F - * @arg RCC_FLAG_HSERDY: HSE oscillator clock ready
6 u0 E# ?, I+ P - * @arg RCC_FLAG_PLLRDY: PLL clock ready
) j. N5 @: L9 O8 A% f: q r - * @arg RCC_FLAG_LSERDY: LSE oscillator clock ready
R; \. i2 J9 X9 y - * @arg RCC_FLAG_LSIRDY: LSI oscillator clock ready
. \7 D3 {8 ] Z5 Z8 r6 l3 n4 [ - * @arg RCC_FLAG_PINRST: Pin reset( Z$ L: L$ {- ]0 w ^# `
- * @arg RCC_FLAG_PORRST: POR/PDR reset
- u" R5 y1 h$ V3 ^/ ~; O" V - * @arg RCC_FLAG_SFTRST: Software reset3 J: I% Y& G/ v- k
- * @arg RCC_FLAG_IWDGRST: Independent Watchdog reset# A! Z) J$ @6 u) I: o( \; U5 C' T
- * @arg RCC_FLAG_WWDGRST: Window Watchdog reset" f$ H# x+ E5 @' \7 p$ q) s3 i) p
- * @arg RCC_FLAG_LPWRRST: Low Power reset
! q$ K5 z0 p2 ?. s* m$ y4 ^ - * $ f! O+ k/ @7 R2 H9 R: ]* k7 y
- * @retval The new state of RCC_FLAG (SET or RESET).
' i- N: G* g6 z, I8 k - */% v D( G) d, Q V0 m
- FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG)5 _: L0 Y* Z" @
- {* e# O3 O: b( b9 n
- uint32_t tmp = 0;/ h0 t( |$ \6 G9 g5 B, ~
- uint32_t statusreg = 0;
& p; a4 F! s9 W7 H - FlagStatus bitstatus = RESET;
?4 p1 U: [+ y. X7 ?% V' h - /* Check the parameters */6 Z2 x9 z0 ~" q
- assert_param(IS_RCC_FLAG(RCC_FLAG));, ?" u; [6 d5 c
) t& U! I, O9 @( c+ M- /* Get the RCC register index */
& R, P4 O7 x% d: g - tmp = RCC_FLAG >> 5;$ {/ S% X" t* Y' }1 ~6 u. N' ?
- if (tmp == 1) /* The flag to check is in CR register */
/ k8 @5 x) A# a - {) Q6 X6 ^8 F4 B3 L' J, a0 Z) S1 y
- statusreg = RCC->CR;
" l$ p- l. T4 R! g; h' J& D - }
3 f- D' ~- F8 ^. B& P2 f - else if (tmp == 2) /* The flag to check is in BDCR register */
* S9 f6 F3 Q3 ^+ v8 }8 g" }2 \ - {
( u: q& J) p- i. ?9 K( D - statusreg = RCC->BDCR;6 x4 r6 G* u1 F: a9 q
- }- _5 D% S' z5 H. S+ i/ ^% P
- else /* The flag to check is in CSR register */% J- m0 X1 Y* Q6 V: Y$ p3 v) a# Q
- {+ y/ A2 O( D5 ?, O$ t2 W! O
- statusreg = RCC->CSR;
6 G8 S d, L3 l" l+ X; a- O - }7 x: P* R8 x3 ]( T9 ]( I5 Q
- ; S; P) O1 S8 G) |
- /* Get the flag position */, x) w2 U" u3 a
- tmp = RCC_FLAG & FLAG_Mask;: e. @6 B+ y( @( G; r5 S
- if ((statusreg & ((uint32_t)1 << tmp)) != (uint32_t)RESET)
1 ^+ N7 F. v% C6 P) b - {
! @/ W, ]# d7 C# g - bitstatus = SET;
1 M4 ], ] X5 E - }
& \ m2 g/ V( q/ \7 }. v - else
# e( I# ?6 t. t/ |; e - {! E' U5 I! i( I4 Q5 c
- bitstatus = RESET;
; S, _' C6 }, H3 t - }& e) h3 t; g' t" Z
M" F R" q! I) j- /* Return the flag status */
2 o$ y( W( C$ G* \% x - return bitstatus;3 D& H ^$ s% O$ z
- }
复制代码 较部分固件库函数,其中多了以下部分——获取RCC寄存器索引,从而得到指定标志所在的位置:7 X1 v& x0 Z9 ?5 X& p* D. ~9 ]
- /* Get the RCC register index */+ J/ Y0 e0 T! ~5 |) p4 @
- tmp = RCC_FLAG >> 5;. M% o4 L2 @1 A7 _& h: G
- if (tmp == 1) /* The flag to check is in CR register */% y- f% E# k2 ~9 u6 o4 Q$ [
- {
0 b A$ k! F- Q' O1 A- o - statusreg = RCC->CR;
0 ?" u' s3 G' [; M8 A - }
* w5 F$ K8 y- w: v - else if (tmp == 2) /* The flag to check is in BDCR register */2 S) N* M9 H6 w* j
- {% }" `6 @) w$ a# F$ h0 Y
- statusreg = RCC->BDCR;
3 c. `2 k* X# y6 X6 t9 E - }" c( {# E, |- u
- else /* The flag to check is in CSR register */
* X% P! {- I$ G: I3 g$ N - {
5 c. g; ` b8 N. R% X" ^" | f ` - statusreg = RCC->CSR;
- K) \6 r; \# R1 u0 h Z) D - }
/ e4 `1 Y' H8 m$ Q+ F5 C! p9 n
, R$ l( j+ k8 x. b# u {- /* Get the flag position */6 N) L, u$ M/ J1 D1 V
- tmp = RCC_FLAG & FLAG_Mask;
1 T! {- D7 O" Y/ |# W - if ((statusreg & ((uint32_t)1 << tmp)) != (uint32_t)RESET)
; k. B9 O+ y2 s T" N! g) r/ { - { R+ m6 f* f" E0 [
- bitstatus = SET;& j4 R$ Q" ]% [1 ^' Y) o7 K
- }& D) a' n- B! p0 l- U1 V
- else
; O, F" R, c# L2 S8 c( J5 f - {+ w! U- g1 j* @) \6 j9 T) u
- bitstatus = RESET;
1 ~8 o; }, ]3 ] - }
复制代码 而在 “stm32f10x_rcc.h” 里对各标志位进行了如下宏定义:
0 O: e* X( g$ \- j7 d3 o- #define RCC_FLAG_HSIRDY ((uint8_t)0x21)
- ` W2 q5 u9 s' s - #define RCC_FLAG_HSERDY ((uint8_t)0x31)
1 |: @! q4 r0 J: v! A* j - #define RCC_FLAG_PLLRDY ((uint8_t)0x39)
5 N! V: k+ e# r4 a' S - #define RCC_FLAG_LSERDY ((uint8_t)0x41)
: d" g& `" A1 [" b* @" Q. x - #define RCC_FLAG_LSIRDY ((uint8_t)0x61)' S' i% A. B3 \5 O3 P
- #define RCC_FLAG_PINRST ((uint8_t)0x7A)
/ Y4 W! o& ^2 M! L( V8 P - #define RCC_FLAG_PORRST ((uint8_t)0x7B); w" S& h/ z* f! r4 E( @
- #define RCC_FLAG_SFTRST ((uint8_t)0x7C)+ T% q" K: r; j; \! C9 y7 G
- #define RCC_FLAG_IWDGRST ((uint8_t)0x7D)
4 X% c; E! ^% k - #define RCC_FLAG_WWDGRST ((uint8_t)0x7E)1 o( h- R. B9 m6 {* l9 l) t
- #define RCC_FLAG_LPWRRST ((uint8_t)0x7F)
复制代码 研究过库函数的贴友想必注意到过:以上宏定义形式没有以下直接与寄存器32个位相对应的形式容易理解:
5 B- F: v8 |# G( x3 z& `; o- #define RCC_SYSCLKSource_HSI ((uint32_t)0x00000000)
7 N% d) E, R: K* s- q6 M - #define RCC_SYSCLKSource_HSE ((uint32_t)0x00000001)
8 g. y, b) e. H! l+ t& ^ - #define RCC_SYSCLKSource_PLLCLK ((uint32_t)0x00000002)
* ?: O; S9 S0 k
复制代码
% x% ^' s# _8 e/ @' M7 n那么,那8位的数据是怎么来的呢?2 B! M3 |% [% T$ ^ w. c
' p# _# T0 C; @( n; r: t
其实,也并没有太大的区别。( K& C G* P& z2 ^ D6 o" t
6 a8 M" U& I3 R9 O( T4 o首先,获取RCC寄存器索引这一步容易理解——那11个标志并不在同一个寄存器里,而是在三个不同寄存器里。语句“RCC_FLAG >> 5” 将宏定义给标志变量的数据左移五位(即数据的低五位被移除)后赋值给变量tmp,所以这里暂时不考虑数据的低五位。, F; S6 A! I$ |- c0 f
- /* Get the RCC register index */
- D1 `5 g/ R3 D4 ~: W" M - tmp = RCC_FLAG >> 5;
4 n6 } r& n' @ - if (tmp == 1) /* The flag to check is in CR register */8 w5 {9 S$ v. H! U! @' @3 q6 \
- {4 u9 [4 [( d0 b0 P( O- ~' h* A
- statusreg = RCC->CR;8 H. X6 s/ \: |; ~ [
- }; F, G4 t9 o- s% N
- else if (tmp == 2) /* The flag to check is in BDCR register */4 Q: H8 I- t, C
- {
/ w5 U" R, {( e3 p) Q - statusreg = RCC->BDCR;1 D9 I7 _( d# s# B# H6 e# f# i! w) j
- }8 [* b$ U# _+ z- [5 r* f
- else /* The flag to check is in CSR register */: i0 L0 w. h+ N9 C: w
- {
8 ^. _5 g3 [% D( {- L0 d" V, o - statusreg = RCC->CSR;6 ^" h9 w$ b: j7 v
- }
复制代码 因为11个标志分布在三个寄存器里,所以以上代码中有三种判断结果,因此要保证在同一寄存器的标志对应的标志变量的数据的高三位要相同(如下所示),而具体数值则要结合寄存器个数和函数来考量。
3 X" U5 g5 n9 X+ a" h! n1 w 标志变量 数据高三位- M* T+ V8 k' y& s, E
RCC_FLAG_HSIRDY 001* w; w" D" N9 ^' E: b! O$ q
RCC_FLAG_HSERDY 001( J2 N9 _& x. _5 w* y$ T- g1 f5 w/ j/ H
RCC_FLAG_PLLRDY 0018 c+ _/ ]2 ?% G. \
RCC_FLAG_LSERDY 010
0 d- L9 H8 }0 B2 f/ Z6 Z6 W RCC_FLAG_LSIRDY 011
7 U! e8 r& u* H8 k5 M; b. | RCC_FLAG_PINRST 011
* f, ^! O* P$ b1 y, R' u! { RCC_FLAG_PORRST 011
5 n0 B) V- C8 z& n$ v& j0 V* F RCC_FLAG_SFTRST 011
5 {( F8 v4 }2 G/ m2 ]" R( z" ^$ l RCC_FLAG_IWDGRST 011: Z% C5 n) }9 T0 ~, O( q$ T
RCC_FLAG_WWDGRST 011. J) l7 F9 k( ?& u$ v
RCC_FLAG_LPWRRST 011
) E' [$ Y @: @; R
* `+ m. C+ w% Z- @( U其次,得到指定标志在所在寄存器的具体位置:
- r' `4 o$ b- r/ Z% z& V- #define FLAG_Mask ((uint8_t)0x1F)
复制代码- /* Get the flag position */7 @, s* D& n, V1 Q- J4 A* _/ M+ M
- tmp = RCC_FLAG & FLAG_Mask;
+ U5 a# N6 j$ M4 E% o7 ` U( k% i' N - if ((statusreg & ((uint32_t)1 << tmp)) != (uint32_t)RESET)& z7 N, L9 g; p3 h# d
- {6 D+ t' ~, K1 k( s' _9 \
- bitstatus = SET;
0 b# @. B: r) C) k0 [+ M% J - }+ k8 G4 B2 X: f
- else
1 e0 H! O6 v- Y5 X% Q5 r& _% L - {( r% M4 b' e: h6 l- o. N
- bitstatus = RESET;
6 K6 W- F3 Z' M* {$ ?; c6 K5 S - }
复制代码 似乎可以像如下这样理解:
+ t8 R5 h+ f" \: K* a3 M6 r# g- /****** 数据<font color="Red">低五位</font>表示<b><font color="Red">该标志位在所在寄存器的第几位</font></b>。 ******/
) l) F7 y0 z6 l% G2 x - /****** 将前面宏定义备注上二进制数据如下 ******/5 ?& s* U/ s! ]/ P
- #define RCC_FLAG_HSIRDY ((uint8_t)0x21) // 001 00001 (低五位值:1)& V C2 L8 z* x5 ]+ M
- #define RCC_FLAG_HSERDY ((uint8_t)0x31) // 001 10001 (低五位值:17)
+ S+ R4 X& }8 j6 ~0 ]+ f2 I( l - #define RCC_FLAG_PLLRDY ((uint8_t)0x39) // 001 11001 (低五位值:25)
9 Q7 I* |6 S" _ m3 H+ l - #define RCC_FLAG_LSERDY ((uint8_t)0x41) // 010 00001 (低五位值:1)- v3 E& S$ l, y7 m* \
- #define RCC_FLAG_LSIRDY ((uint8_t)0x61) // 011 00001 (低五位值:1)# |! q. y6 h" D) h
- #define RCC_FLAG_PINRST ((uint8_t)0x7A) // 011 11010 (低五位值:26)6 F8 ~) Q/ z& i1 Q$ ~& q
- #define RCC_FLAG_PORRST ((uint8_t)0x7B) // 011 11011 (低五位值:27). L7 k3 v, L2 N2 h& N# h/ z
- #define RCC_FLAG_SFTRST ((uint8_t)0x7C) // 011 11100 (低五位值:28)
, i, Q% P5 }7 x/ w4 v7 X - #define RCC_FLAG_IWDGRST ((uint8_t)0x7D) // 011 11101 (低五位值:29): ], b/ @# W8 t" y; N# @1 F
- #define RCC_FLAG_WWDGRST ((uint8_t)0x7E) // 011 11110 (低五位值:30)- o; @" d/ E4 j: [( ^# Y! G
- #define RCC_FLAG_LPWRRST ((uint8_t)0x7F) // 011 11111 (低五位值:31)
复制代码 比如前三个变量所对应的标志分别在RCC_CR寄存器的第1、17、25位。如下图所示:* v, r" n+ t( Y: S
RCC_CRå¯åå¨
8 ~. ~. q( A* `( n而第四个变量所对应的标志在RCC_BDCR寄存器的第1位。
7 X$ A/ t% y! O* n, ~( C
3 E* k3 ^; [2 j8 }) {/ q8 i后七个变量所对应的标志分别在RCC_CSR寄存器的第1、26~31位。2 m) e* l/ D. B
8 J, j/ j+ [$ C: W9 A这样,执行以下语句即可判断指定位的状态。
" J5 \$ D% _& ~: G; a2 E# ]- tmp = RCC_FLAG & FLAG_Mask;
- N" A. [6 i7 P2 T% F- Y - if ((statusreg & ((uint32_t)1 << tmp)) != (uint32_t)RESET)( c& V5 U+ C( t8 f N+ H ~" w/ K& p
- {
* T& z9 B b+ S -
0 F, `" B1 z' j6 g - }
复制代码 显而易见,固件库函数之所以采用这种编程思路,目的之一就是为了避免当多个同类型标志不在同一寄存器时程序太繁杂。1 }2 V% h1 a" }; u
# x- M; q. z8 y' \
除了RCC_GetFlagStatus()函数,固件库中还有其它函数也采用了同样的编程思路。; W- I# @8 `: M1 I6 C; v+ ^
1 T8 K% o: e6 Q- Q----------------------------------------------------------------------------------------------------------------------------------------------7 ]0 b7 o$ B7 i6 D5 O- y
32初学者,在各论坛没搜到过类似帖,不知自己是否眼盲(或者太无知,就这么一个问题还发帖 ),也不知自己所理解的是否正确。) y/ T% A3 r8 s& d
若理解有误,还望广大贴友指正,非常感谢!/ j& o, D4 |6 t4 L' I% Y+ c
----------------------------------------------------------------------------------------------------------------------------------------------
% Y$ C- h5 m6 C$ u- f, v% e5 ?2 f7 Q0 o5 C% t& }
|
谢谢欧巴前辈,学习之路还请多多指教。