TA的每日心情 | 开心 2023-5-15 15:14 |
---|
签到天数: 1 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
. r. P1 b& x; R! {# J) M! Q( y! h6 g |, Q
在 STM32F4 标准固件库里,时钟源的选择以及时钟使能等函数都是在RCC相关固件库文件stm32f4xx_rcc.h 和 stm32f4xx_rcc.c 中声明和定义的。大家打开 stm32f4xx_rcc.h 文件可以看到文件开头有很多宏定义标识符,然后是一系列时钟配置和时钟使能函数申明。这些函数大致可以归结为三类,一类是外设时钟使能函数,一类是时钟源和分频因子配置函数,还有一类是外设复位函数。当然还有几个获取时钟源配置的函数。下面我们以几种常见的操作来简要介绍一下这些库函数的使用。
' d0 W! J- |0 u( y- M- n
( [- |, {. e/ C& a首先是时钟使能函数。时钟使能相关函数包括外设设置使能和时钟源使能两类。首先我们来看看外设时钟使能相关的函数:
) ]9 M; ^. h7 p# c8 f, G, \; D$ }9 m
6 f: [- S+ c+ x) \) @, jvoid RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);& b+ P" u6 ~' |; i! j+ E
( w* ^) k( B7 _' @
void RCC_AHB2PeriphClockCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState);$ h' s5 H/ ?7 ]* O
. @/ D: a; ~9 ?$ o
void RCC_AHB3PeriphClockCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState);3 `+ A0 P* o g
' {3 T) {1 X: w. W
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);4 f! B6 Z ^! |
8 r$ D& u: K! c; D# f1 Bvoid RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
9 j# h9 S) Q. Y7 s$ J% m. {9 Q3 W9 a6 f' m6 X+ H! B
这里主要有 5 个外设时钟使能函数。5 个函数分别用来使能 5 个总线下面挂载的外设时钟,这些总线分别为:AHB1总线,AHB2总线,AHB3总线,APB1总线以及APB2总线。要使能某个外设,调用对应的总线外设时钟使能函数即可。
+ `1 G( m% i* A. D M1 Q) k. G
) V7 e8 p1 y% {/ M& S3 } 这里我们要特别说明一下,STM32F4 的外设在使用之前,必须对时钟进行使能,如果没有使能时钟,那么外设是无法正常工作的。对于哪个外设是挂载在哪个总线之下,虽然我们也可以查手册查询到,但是这里如果大家使用的是库函数的话,实际上是没有必要去查询手册的,这里我们给大家介绍一个小技巧。6 o9 u# e% ~$ }9 u
3 o2 f. U" X1 A7 Q, b 比如我们要使能GPIOA,我们只需要在stm32f4xx_rcc.h 头文件里面搜索GPIOA,就可以搜索到对应的时钟使能函数的第一个入口参数为 RCC_AHB1Periph_GPIOA,从这个宏定义标识符一眼就可以看出,GPIOA 是挂载在 AHB1 下面。同理,对于串口 1 我们可以搜索 USART1,找到标识符为RCC_APB2Periph_USART1,那么很容易知道串口1是挂载在APB2之下。这个知识在我们后面的“4.7 快速组织代码技巧”小节也有讲解,这里顺带提一下。
- a. P. w1 C, o+ v+ c
0 \( J1 e8 `: l2 G* C; u0 O4 G 如果我们要使能 GPIOA,那么我们可以在头文件stm32f4xx_rcc.h 里面查看到宏定义标识符RCC_AHB1Periph_GPIOA,顾名思义 GPIOA 是挂载在 AHB1 总线之下,所以,我们调用AHB1总线下外设时钟使能函数RCC_AHB1PeriphClockCmd 即可。具体调用方式入如下:. m/ e3 R) Y7 |% v+ R) Y E- G/ @
; s8 D: \. f" I! c; Y( s7 d4 IRCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//使能 GPIOA时钟( Y2 \& \6 @; v# d- c! ^- U
. E8 d1 q1 x+ o6 k3 R同理,如果我们要使能串口1 的时钟,那么我们调用的函数为:
, c. v, R' I, n d
# M0 _, Z4 T+ H2 P: Xvoid RCC_AHB2PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);+ m* w+ c# m: c" ^4 A4 w
! K5 m- `! ^, Z3 }; }
具体的调用方法是:# r' V) _ c% P# V$ N. ^
. l5 l" B' m5 H/ o: u1 XRCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
8 L; G) ]0 c- W; N1 F0 o) A" o5 T, n& }5 @5 X. F* V# Y. e
还有一类时钟使能函数是时钟源使能函数,前面我们已经讲解过 STM32F4 有 5 大类时钟源。这里我们列出来几种重要的时钟源使能函数:
! Y8 K3 w, W9 H6 O, d$ }$ h! f
- g: s% K$ ]# [ t: d3 D void RCC_HSICmd(FunctionalState NewState);
: Y/ ] A( z5 a7 T3 o9 h) Q
! l. d: T( o! X- a0 Evoid RCC_LSICmd(FunctionalState NewState);/ h! V' x R$ V% F5 a9 M( _' D: k# n8 x
3 f& I$ D& Y7 T; Z; ]' ]. @1 u; h
void RCC_PLLCmd(FunctionalState NewState);
) j& h! s9 \* j" b" l, j3 Z2 N# M
* d, b* a V1 `! a: C+ R1 ]void RCC_PLLI2SCmd(FunctionalState NewState);4 P% s: G& }' u
6 V: j$ X3 l% S
void RCC_PLLSAICmd(FunctionalState NewState);9 C% \" i( S8 g
4 O8 n! l% l8 q6 V/ Rvoid RCC_RTCCLKCmd(FunctionalState NewState); X$ a- I2 z, [
& b9 Y* d3 d/ x5 s; }这些函数是用来使能相应的时钟源。比如我们要使能PLL时钟,那么调用的函数为:$ |0 U) h8 H. v
! c8 I& u$ p: t$ `void RCC_PLLCmd(FunctionalState NewState);
7 n3 e6 G8 @+ N) {. L8 u U7 f5 i' k2 e
具体调用方法如下:
5 e9 Q8 O% u* Y" J7 b5 ?# _
' ?2 D% J7 o' k1 |. L. t5 R* f; P RCC_PLLCmd(ENABLE);
% z" U5 W6 O; t6 J$ L) R, E# q8 t+ S8 ~0 n7 u- [3 L
我们要使能相应的时钟源,调用对应的函数即可。
9 W" q# ?2 o. m. {/ ^* ~: B& B2 X+ Z1 Q& D3 t. m
接下来我们要讲解的是第二类时钟功能函数:时钟源选择和分频因子配置函数。这些函数是用来选择相应的时钟源以及配置相应的时钟分频系数。比如我们之前讲解过系统时钟SYSCLK,我们可以选择HSI,HSE以及PLL三个中的一个时钟源为系统时钟。那么到底选择哪一个,这是可以配置的。下面我们列举几种时钟源配置函数:4 m8 S3 z0 K4 K0 D* w
1 Q! B6 P8 R3 U* l4 ?' ]; L; N void RCC_LSEConfig(uint8_t RCC_LSE);
2 h1 |: B' ?: h, \3 k
* e, _4 d/ f0 D) z1 O2 Dvoid RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);9 w+ O# J/ T+ q7 w
; ^8 n8 i. `$ k1 f/ M/ ~/ L4 |& ovoid RCC_HCLKConfig(uint32_t RCC_SYSCLK);
9 h) c: s- ?) x. h, `: w. v
( p; z# h% C, \1 b( J2 t. ~! P2 Xvoid RCC_PCLK1Config(uint32_t RCC_HCLK);: l. k9 ~( }( u* Y% g
7 S3 i1 { D& x! |9 ~7 t. _
void RCC_PCLK2Config(uint32_t RCC_HCLK);
/ V2 K' x% i( L, R9 e+ u8 T% s! ^* I( v7 x. i
void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource);
8 L+ m0 w& ?/ W6 A6 C
# h1 D0 G6 b: q+ b' Y+ L M* I9 q* ovoid RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t PLLM,
2 J( \( p; V- \7 @: i9 u5 v, [2 v c
uint32_t PLLN, uint32_t PLLP, uint32_t PLLQ);$ k$ q. o) I G
. g( X! U X. Y% t: p$ h; h
比如我们要设置系统时钟源为HSI,那么我们可以调用系统时钟源配置函数:
0 m1 G) e e9 J+ G2 t
$ J3 s6 c6 ^, \+ q, kvoid RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);/ [ g6 Y% S7 |9 n
5 u+ e0 P7 |. u& n7 h: K
具体配置方法如下:) ^* O: h* L- f
o) G1 D) v9 I# L& s% B8 P9 A6 O
void RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);//配置时钟源为HSI
) i# J1 e4 v, _5 z6 V4 z4 @# ]. P7 ^$ h, l+ S8 }: L4 Q/ j8 \& [
又如我们要设置APB1 总线时钟为HCLK的 2分频,也就是设置分频因子为2分频,那么 如果我们要使能HSI,那么调用的函数为: d- h6 G3 d4 X; u2 Z' D; L
6 h' f- T$ i: c4 I. n# M" }5 _1 }void RCC_PCLK1Config(uint32_t RCC_HCLK);
" U! Q1 j- `2 K) h& ?% ^8 f$ `0 K! F# l+ f% J. l) O" J
具体配置方法如下:% r6 N V W% ]
. s8 a R; b( H
RCC_PCLK1Config(RCC_HCLK_Div2);9 Q' v2 s2 ~# y! l, r: P' G5 D; ]
9 x9 Z1 H# _( w5 l
接下来我们看看第三类外设复位函数。如下:+ V0 c+ M+ I. Z+ U* `( r
1 u! g% i; f$ l# d8 {2 f. f% Qvoid RCC_AHB1PeriphResetCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);4 m/ [2 k6 `! a4 j4 v
4 D3 L. \/ q' V3 j
void RCC_AHB2PeriphResetCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState);
! `' ~4 U( ]2 P. A9 t
7 G( H8 l/ `- a" T3 _void RCC_AHB3PeriphResetCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState);7 y! A9 t( g9 J, C
T/ L, m; n1 C
void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
3 [4 V1 t# m, D, Q! A. x1 @" D% o
void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);* G" k: t5 P4 @9 T7 M( V
& x" l& T$ _! z& A* f- k6 T 这类函数跟前面讲解的外设时钟函数使用方法基本一致,不同的是一个是用来使能外设时钟,一个是用来复位对应的外设。这里大家在调用函数的时候一定不要混淆。
* z8 e5 a7 E/ [2 N" i6 n
5 K% \! ]: Y) K' j0 v 对于这些时钟操作函数,我们就不一一列举出来,大家可以打开RCC对应的文件仔细了解。* d+ E2 `" q& E6 F. ~. y5 |
& x. l5 _- ~; d8 c; P5 A6 G* y
! b: ]$ C" ~" Z
9 r/ A% G$ l) ~! ^5 @; S
% h, d1 x6 }, U/ u9 _3 M* X7 o' I# |. g
7 f2 p0 w! A# l2 b2 E q |
|