TA的每日心情 | 开心 2023-5-15 15:14 |
---|
签到天数: 1 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
6 d/ J; ^5 ? ]. ]
# e6 e* Y/ i& ], [( @, f在 STM32F4 标准固件库里,时钟源的选择以及时钟使能等函数都是在RCC相关固件库文件stm32f4xx_rcc.h 和 stm32f4xx_rcc.c 中声明和定义的。大家打开 stm32f4xx_rcc.h 文件可以看到文件开头有很多宏定义标识符,然后是一系列时钟配置和时钟使能函数申明。这些函数大致可以归结为三类,一类是外设时钟使能函数,一类是时钟源和分频因子配置函数,还有一类是外设复位函数。当然还有几个获取时钟源配置的函数。下面我们以几种常见的操作来简要介绍一下这些库函数的使用。: _+ ?' v B" A/ V5 K/ z7 J7 D
0 g+ d, c4 f% @% d* e$ t _/ Q
首先是时钟使能函数。时钟使能相关函数包括外设设置使能和时钟源使能两类。首先我们来看看外设时钟使能相关的函数:5 o) c; L! `# s' i
* o9 E2 p- b( c% V w3 [& }void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);
8 W- W5 L; H: W' F. y, ~3 E0 D
" R9 X3 _( \5 [% d5 K- H: ]void RCC_AHB2PeriphClockCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState);9 P! x( N I/ D9 h, i
; ^) U, O# ?# o. V# s$ T' S: a7 |
void RCC_AHB3PeriphClockCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState);
$ f. V1 }2 I! C% [, Q4 F& n
. e3 v" o% D2 M3 G, tvoid RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);: P8 ~; t( l2 U0 b* J1 W. w* a0 f0 E
, `1 x6 u: Y+ U9 M0 ~# T; B8 J- Q
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
3 A( ^) }+ \7 M% V3 f: M
: z* s" s0 ?! ]( a$ t- J* J这里主要有 5 个外设时钟使能函数。5 个函数分别用来使能 5 个总线下面挂载的外设时钟,这些总线分别为:AHB1总线,AHB2总线,AHB3总线,APB1总线以及APB2总线。要使能某个外设,调用对应的总线外设时钟使能函数即可。! Q) T0 u9 J' s3 ?" W4 c8 F
. ~( O. T- V; s2 L2 ^* K
这里我们要特别说明一下,STM32F4 的外设在使用之前,必须对时钟进行使能,如果没有使能时钟,那么外设是无法正常工作的。对于哪个外设是挂载在哪个总线之下,虽然我们也可以查手册查询到,但是这里如果大家使用的是库函数的话,实际上是没有必要去查询手册的,这里我们给大家介绍一个小技巧。
8 H* M- `4 p+ W+ d4 Q! \. w5 r( E+ Z$ q# t; J# ?% f N5 a
比如我们要使能GPIOA,我们只需要在stm32f4xx_rcc.h 头文件里面搜索GPIOA,就可以搜索到对应的时钟使能函数的第一个入口参数为 RCC_AHB1Periph_GPIOA,从这个宏定义标识符一眼就可以看出,GPIOA 是挂载在 AHB1 下面。同理,对于串口 1 我们可以搜索 USART1,找到标识符为RCC_APB2Periph_USART1,那么很容易知道串口1是挂载在APB2之下。这个知识在我们后面的“4.7 快速组织代码技巧”小节也有讲解,这里顺带提一下。# [; E8 [0 l Y* }! u/ \# w
/ j* g7 u) o) X8 e" ]5 a 如果我们要使能 GPIOA,那么我们可以在头文件stm32f4xx_rcc.h 里面查看到宏定义标识符RCC_AHB1Periph_GPIOA,顾名思义 GPIOA 是挂载在 AHB1 总线之下,所以,我们调用AHB1总线下外设时钟使能函数RCC_AHB1PeriphClockCmd 即可。具体调用方式入如下:
. ]% R* Y0 M+ h* E+ l, K
# G4 A" M0 \0 aRCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//使能 GPIOA时钟% D9 S& Y) l/ ]# `" ~$ X
2 i1 g) k) o2 P2 ]+ Z& z8 n同理,如果我们要使能串口1 的时钟,那么我们调用的函数为:
4 c/ ^0 R( Y9 X5 S/ ?6 ]7 [/ i9 F# v% T% s
void RCC_AHB2PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);
. {: x/ m4 \2 q) \- `- k# r6 X. j# i, G" ~, r* t
具体的调用方法是:
" n% E" m9 @) a7 T/ u+ X/ I) K4 b; h$ m
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
6 t6 L% B9 y# B% l0 x
% s1 V1 F$ q" L7 S7 f! @还有一类时钟使能函数是时钟源使能函数,前面我们已经讲解过 STM32F4 有 5 大类时钟源。这里我们列出来几种重要的时钟源使能函数:
5 e' M- E6 E6 B& R
# U( l2 _$ x2 s void RCC_HSICmd(FunctionalState NewState);
0 r, m. g$ O5 H- G$ y
) s* N& d0 v6 z3 T% B2 Qvoid RCC_LSICmd(FunctionalState NewState);
9 y; i) q, |+ \
. z3 P3 T8 \5 W% s" h# wvoid RCC_PLLCmd(FunctionalState NewState);1 A6 ^* c* J* D3 b1 a
& o4 @: v' i8 A/ Y
void RCC_PLLI2SCmd(FunctionalState NewState);
# w& n. g9 P: ?4 u& i5 s, [: @* [/ F: L9 H C' c2 Q
void RCC_PLLSAICmd(FunctionalState NewState);% ` J+ W# {- f _* E) R
) z9 p3 H! b* _) d4 uvoid RCC_RTCCLKCmd(FunctionalState NewState);' P2 i& R% w7 l( M: J0 g, t+ w6 K
" L3 W6 C) A7 }9 o, g
这些函数是用来使能相应的时钟源。比如我们要使能PLL时钟,那么调用的函数为:2 Z' h9 h' V! S& i
7 L$ \5 B0 v7 [" ^7 S0 q t7 a m( Zvoid RCC_PLLCmd(FunctionalState NewState);
! v% \9 B8 ` C3 {, @4 T; n7 F: a$ T' B5 p" z/ b0 V3 n
具体调用方法如下:
! r7 K9 ?" a" {8 P8 G- T2 t% V! I" w* p Z
RCC_PLLCmd(ENABLE);
/ E1 {( P; }# M" L5 B1 [2 e" m6 c9 e! L: r5 ?
我们要使能相应的时钟源,调用对应的函数即可。, l" q, S# q/ f+ q9 X; Z' ?9 |9 {
, r, `1 G; y; c# p7 |
接下来我们要讲解的是第二类时钟功能函数:时钟源选择和分频因子配置函数。这些函数是用来选择相应的时钟源以及配置相应的时钟分频系数。比如我们之前讲解过系统时钟SYSCLK,我们可以选择HSI,HSE以及PLL三个中的一个时钟源为系统时钟。那么到底选择哪一个,这是可以配置的。下面我们列举几种时钟源配置函数:6 A" N: p) B9 t# k# r6 B' c/ q
5 d: O! r' y) Y8 G void RCC_LSEConfig(uint8_t RCC_LSE);* X1 Q2 [; N" m- _- Z. ]# O
7 e- L# @# ^8 w: c3 l, y
void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);8 {1 {' b, l# Q, o8 N$ l7 E8 G8 t- ^
+ ~+ T) I# U' r. S2 ~: b' H' N) a
void RCC_HCLKConfig(uint32_t RCC_SYSCLK);
' z b, y" R1 V. O' P7 J5 s V% t1 a. q0 j" |: U) C
void RCC_PCLK1Config(uint32_t RCC_HCLK);$ ?( @* r$ K) J& w9 Z
, y9 |' {# H \& d
void RCC_PCLK2Config(uint32_t RCC_HCLK);
3 @0 J* R: c {) S D5 E0 M, r7 l& e( ]: B& N
void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource);6 m- Q" v4 `/ o- I( i, G" u
; V9 w! e$ V1 ^3 u& [' P& X* kvoid RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t PLLM, 8 g: x2 h& `" m. m: c/ K; {! i; ?* r! s
4 t) f: v8 `& |) C1 w" j, X
uint32_t PLLN, uint32_t PLLP, uint32_t PLLQ);. t0 t8 C" H$ `4 W( {) \# z
) B0 @8 A' {0 \; X- U
比如我们要设置系统时钟源为HSI,那么我们可以调用系统时钟源配置函数:
n- w/ {! a, j: w0 d$ ^3 ?8 r4 L& M V# O) R, L
void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);
# P& N) a! R7 W4 N
5 S5 I4 i2 c$ ? I具体配置方法如下:
& y8 X t6 f* m7 k# c
8 J7 Q( [- j+ |& _/ t: K! {2 Hvoid RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);//配置时钟源为HSI1 t) Q7 y# X9 X: l. X9 r2 E
3 E$ O( V9 e5 } 又如我们要设置APB1 总线时钟为HCLK的 2分频,也就是设置分频因子为2分频,那么 如果我们要使能HSI,那么调用的函数为:, \" T; V3 r* F
! t, E: k! E C! q. B, q+ qvoid RCC_PCLK1Config(uint32_t RCC_HCLK);
7 S6 f- w& X* p# A/ N6 A/ G6 H- f$ r Z, @, |
具体配置方法如下:
1 r% e1 D9 A2 a
% d/ w3 T0 R9 u8 m# ZRCC_PCLK1Config(RCC_HCLK_Div2);
) O5 V, ]# [2 q- l5 r& }
- p) U( I1 C. d* |" Z 接下来我们看看第三类外设复位函数。如下:7 X& {; d3 N( {
8 K9 C! |& c4 A. ~! {6 Y: F
void RCC_AHB1PeriphResetCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);
4 Y8 u3 a+ q- m% J( g7 i: w" y$ f, T* P7 U8 C N! W u
void RCC_AHB2PeriphResetCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState);
$ g7 z" Z6 _( Y" D2 `4 T4 R0 _: z3 c! m1 x% a7 W' Q+ h1 [
void RCC_AHB3PeriphResetCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState);& B- K' y5 r% Q) o m$ s( \
6 a5 I& V! W$ k- P: g0 u Z
void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
, }. y+ g X9 O( _( J# D9 A) ^5 m* z+ t$ S) B
void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
: q- M' H. G$ o* k$ u' A% p5 S
% h) \! e+ H. y3 P2 e: h |8 S 这类函数跟前面讲解的外设时钟函数使用方法基本一致,不同的是一个是用来使能外设时钟,一个是用来复位对应的外设。这里大家在调用函数的时候一定不要混淆。( T3 y2 u3 c3 u$ n
7 f7 Z. Q6 H! L! X" p 对于这些时钟操作函数,我们就不一一列举出来,大家可以打开RCC对应的文件仔细了解。
# x! s" a0 p+ e0 p: ~
K) \! y/ _9 G3 l$ A
. U. x6 e% Z0 v( T( ~1 L. f, ]* ?- q7 i- q7 q: A F) O6 h
; `9 B" b* t: j* h
) A" |. D4 P3 Y5 I |
|