TA的每日心情 | 开心 2023-5-15 15:14 |
---|
签到天数: 1 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
; f* |6 i) h5 O; X: | q: P( ?& M/ p+ F. s/ N
在 STM32F4 标准固件库里,时钟源的选择以及时钟使能等函数都是在RCC相关固件库文件stm32f4xx_rcc.h 和 stm32f4xx_rcc.c 中声明和定义的。大家打开 stm32f4xx_rcc.h 文件可以看到文件开头有很多宏定义标识符,然后是一系列时钟配置和时钟使能函数申明。这些函数大致可以归结为三类,一类是外设时钟使能函数,一类是时钟源和分频因子配置函数,还有一类是外设复位函数。当然还有几个获取时钟源配置的函数。下面我们以几种常见的操作来简要介绍一下这些库函数的使用。% J, n# k$ _) Z
5 q% A: m& V; E8 l- W! b& K; n首先是时钟使能函数。时钟使能相关函数包括外设设置使能和时钟源使能两类。首先我们来看看外设时钟使能相关的函数:
: |, _# c5 k$ s9 H7 Q
! c- N7 e$ O8 q$ |& |void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);
) g1 _+ S; W8 q8 v9 C4 c9 u# R% K* v6 N# _
void RCC_AHB2PeriphClockCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState);
2 D; w# q6 U5 N3 k. A8 I/ v, }' Y$ i8 O T6 M, A
void RCC_AHB3PeriphClockCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState);* I! o9 Y% b: U8 P+ _ W/ Y
, d3 q O2 p5 y* r* ^3 j5 {3 v
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);+ v. g* |4 Y# g N% c7 K
; i8 M7 A# I9 }- T% U( l7 ~) P4 @9 ovoid RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
5 w3 J% h. D9 p$ n2 a% _# L+ ? B/ {) @7 t2 g9 }) d
这里主要有 5 个外设时钟使能函数。5 个函数分别用来使能 5 个总线下面挂载的外设时钟,这些总线分别为:AHB1总线,AHB2总线,AHB3总线,APB1总线以及APB2总线。要使能某个外设,调用对应的总线外设时钟使能函数即可。7 Z9 V0 @9 ]' R7 S) P1 R
5 n- y6 l: M0 T+ d1 e4 } 这里我们要特别说明一下,STM32F4 的外设在使用之前,必须对时钟进行使能,如果没有使能时钟,那么外设是无法正常工作的。对于哪个外设是挂载在哪个总线之下,虽然我们也可以查手册查询到,但是这里如果大家使用的是库函数的话,实际上是没有必要去查询手册的,这里我们给大家介绍一个小技巧。
& _1 v+ ]5 W6 m0 @1 r5 F
; j" g$ U4 N6 [: ? 比如我们要使能GPIOA,我们只需要在stm32f4xx_rcc.h 头文件里面搜索GPIOA,就可以搜索到对应的时钟使能函数的第一个入口参数为 RCC_AHB1Periph_GPIOA,从这个宏定义标识符一眼就可以看出,GPIOA 是挂载在 AHB1 下面。同理,对于串口 1 我们可以搜索 USART1,找到标识符为RCC_APB2Periph_USART1,那么很容易知道串口1是挂载在APB2之下。这个知识在我们后面的“4.7 快速组织代码技巧”小节也有讲解,这里顺带提一下。
. S m Q0 U2 J/ s# C T; [7 {+ ~6 a, u$ m# {6 b. ?, v' w# Y; M
如果我们要使能 GPIOA,那么我们可以在头文件stm32f4xx_rcc.h 里面查看到宏定义标识符RCC_AHB1Periph_GPIOA,顾名思义 GPIOA 是挂载在 AHB1 总线之下,所以,我们调用AHB1总线下外设时钟使能函数RCC_AHB1PeriphClockCmd 即可。具体调用方式入如下:
3 f0 L3 N/ X$ k, n- W* I' P! o" [6 }2 D9 R& |, q$ p. z5 ]
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//使能 GPIOA时钟# k! H( ^7 p% N' _: `% {
! d9 p% S$ o" l5 h* G! d同理,如果我们要使能串口1 的时钟,那么我们调用的函数为:# g# m5 V0 {& i$ W$ g
6 V7 N# G7 N2 }% Z3 p1 D! R7 @: qvoid RCC_AHB2PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);
* P9 g; K( q5 G* J
$ E& V4 m5 [, z/ J/ ~具体的调用方法是:
5 X# k! x7 |7 f! ]5 e1 v* {3 N7 Y& G3 p. \
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
8 H# v2 z- ^: {1 C4 T" `1 @! j
/ N3 N ]6 }/ {还有一类时钟使能函数是时钟源使能函数,前面我们已经讲解过 STM32F4 有 5 大类时钟源。这里我们列出来几种重要的时钟源使能函数:- j1 D$ y; H) l, j
9 X7 F: M- L& ]: H: i H |8 O void RCC_HSICmd(FunctionalState NewState);
' S) i! S" q3 E8 A6 {* O2 ]& d5 p, |( m2 f, M! P s0 d h+ N4 t# g& F
void RCC_LSICmd(FunctionalState NewState);9 s. D$ z) H% {2 |9 ^$ z
. l& j5 B6 p: [void RCC_PLLCmd(FunctionalState NewState);4 R: O: i9 d; M, x2 Q+ X
' R# | r7 L/ X+ A* w& W
void RCC_PLLI2SCmd(FunctionalState NewState);
& j* e7 {9 X0 Q
* V9 `- Q F, b; L. hvoid RCC_PLLSAICmd(FunctionalState NewState);; Q* ?2 R. p" F
9 q1 G- y1 [5 z$ hvoid RCC_RTCCLKCmd(FunctionalState NewState);
# \$ b" E5 a: i8 E5 |9 t0 ~5 c6 f4 z- X. W! E: S
这些函数是用来使能相应的时钟源。比如我们要使能PLL时钟,那么调用的函数为:
; G- s9 S) d' g; H: V7 i8 l" Q3 F% D8 B/ `
void RCC_PLLCmd(FunctionalState NewState);! Z4 [4 z* _9 @
7 b) C, y% h9 O" d S; n+ @具体调用方法如下:6 C8 M" [" F$ i% A5 C- W1 K+ |7 x
& U6 ]; e2 C( `" F2 ` RCC_PLLCmd(ENABLE);
+ H# V1 N2 J% c% g2 Y. O) M6 g6 u4 r' F$ O# U" P7 p. [4 i8 S. J
我们要使能相应的时钟源,调用对应的函数即可。8 a3 n- c4 U3 [+ a* k! E& ~. g
% e3 @; ?, x4 _$ l 接下来我们要讲解的是第二类时钟功能函数:时钟源选择和分频因子配置函数。这些函数是用来选择相应的时钟源以及配置相应的时钟分频系数。比如我们之前讲解过系统时钟SYSCLK,我们可以选择HSI,HSE以及PLL三个中的一个时钟源为系统时钟。那么到底选择哪一个,这是可以配置的。下面我们列举几种时钟源配置函数:0 W( n" y7 ~8 @* u; q
) o+ R; z! Q% u8 l7 r+ e Y( o
void RCC_LSEConfig(uint8_t RCC_LSE);
( B Y7 L9 o* o `- E2 `9 g, o
. ~ |9 z4 ?& Ivoid RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);
5 j7 j! j6 ]1 v# y: H5 Z9 r% { e
, D* I5 O8 g6 d" ~; Y- ^void RCC_HCLKConfig(uint32_t RCC_SYSCLK);; a7 _! d! ?# M7 h4 K
/ W- g- Z( b* O, _void RCC_PCLK1Config(uint32_t RCC_HCLK);
; q' g" A( M5 U1 K4 d- `/ j# g, `; K$ f2 _' h5 d# B- |
void RCC_PCLK2Config(uint32_t RCC_HCLK);4 u4 j- u! p+ v& d) {6 g) [
1 d" ]: r/ R4 C
void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource);
" m, p: r/ o2 t: Z' d9 `! L# l2 b4 _# @
void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t PLLM, 9 k5 b) K7 f! V/ i. e
* e9 H7 T4 J8 Q+ juint32_t PLLN, uint32_t PLLP, uint32_t PLLQ);/ b9 q. P1 F& I; U7 T4 Q. N5 X
5 C/ C l- Z2 O- l( D比如我们要设置系统时钟源为HSI,那么我们可以调用系统时钟源配置函数:3 F! ~# A, r$ a( S7 z6 S2 i
4 l# t5 f4 H. @% S2 {void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);! Q# o2 Z. W! Q' ?' ~& E# D
4 q& z+ c- p f6 i1 N; \: O; f) U具体配置方法如下:2 l+ H# t1 \; W& U$ A' I# {
/ r3 a- Y4 ~8 k$ M8 I' hvoid RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);//配置时钟源为HSI
7 @0 M$ ^$ I& C j+ {( Q# V, a( }8 {5 n' h
又如我们要设置APB1 总线时钟为HCLK的 2分频,也就是设置分频因子为2分频,那么 如果我们要使能HSI,那么调用的函数为:
1 g" {: V4 v9 |3 z& W
5 c* G- r% P( U' }void RCC_PCLK1Config(uint32_t RCC_HCLK);
& J, U! J" b! w; }: I8 b5 L- }4 z8 [" _6 U n; H( A+ y% f
具体配置方法如下:
% p; O a% n' I! ]6 J& s5 k4 v& P" H7 |1 P1 Z4 S
RCC_PCLK1Config(RCC_HCLK_Div2);9 o0 T. ?1 z V9 h: }
; ?. y" S" H) {0 T6 R0 b+ V
接下来我们看看第三类外设复位函数。如下:
+ l9 T% Z% ^; A+ h% {: z6 E8 H: t! k% D0 h1 I7 i
void RCC_AHB1PeriphResetCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);
2 x& i9 w/ Y8 |2 z( a4 @( p6 G3 j. E. @( s. @- S. V' \
void RCC_AHB2PeriphResetCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState);
1 Q s, d4 o# Z" U- w# j5 ?- H& l
void RCC_AHB3PeriphResetCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState);$ m' G/ t) {: V( a' S8 y
% z) G& g9 B7 z$ Z2 [8 s* ?void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
6 N4 J* U/ T- p& |
0 J: u( y( ^8 a: L/ b8 w5 ovoid RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
; S: n2 `) ^; K2 ?0 f/ j" B' E- `5 {* {0 Z. L
这类函数跟前面讲解的外设时钟函数使用方法基本一致,不同的是一个是用来使能外设时钟,一个是用来复位对应的外设。这里大家在调用函数的时候一定不要混淆。
6 [- E- x6 A n3 B$ v$ U3 ] D" D) X" X
对于这些时钟操作函数,我们就不一一列举出来,大家可以打开RCC对应的文件仔细了解。
) P7 A/ A' y% d7 ~+ L, a
; P/ U; W/ h& p( y7 ^7 r
% P. [) ]" k9 ]& F8 y3 f$ Q1 Y4 u o' {0 R, a3 r
- d* z( q; X" b/ A
6 ^# k' A$ A4 D* _/ F; k p+ d T0 U |
|