你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32F207时钟系统解析

[复制链接]
STMCU小助手 发布时间:2021-12-3 17:00
板子使用的是25M无源晶振,下文将介绍STM32F207的时钟系统如何将25M晶振时钟转换为120M系统主频时钟的。
  i) _  R* f4 P; U0 H7 E# M- W9 d& c! _8 R
01、时钟系统介绍
2 ~! j- C- Z' e6 b: n+ [
0 g/ D$ t' b6 t: z; a: p
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

! s- Z8 }$ Y) c( u                                                                    ▲时钟系统专业名词缩写# u% \. q* _4 \# d. c# |! E* }+ |- x
+ b0 T- `( W6 j/ m) w8 @( Z/ Y" p
时钟系统关键组成部分4 }1 Y" f# r3 z* w% s7 Q) C4 h9 p/ Y  L
! |* B) T. r4 O8 J" o( h
01 内部高速时钟(HSI). |8 B! {7 Z$ }

8 y* K: H9 P" h( T) fHSI时钟信号可以通过内部16MHZ的RC振荡器产生,可以直接用于系统时钟或者用于PLL输入。
5 `# q, x. M5 d% f8 C
' ]2 N: N- M) ~. R* Q* x. }8 p: \HSI的RC振荡器的优势是:在最小成本(没有外部器件)情况下提供一个时钟源。它的启动速度要比HSE晶体振荡器更快,但是即使校准频率后,它的精度仍然小于外部晶体振荡器或陶瓷谐振器。
- J3 Q3 _3 s4 A9 r- W
! G$ o$ ^. h5 f. R/ O& g! W02 外部高速时钟(HSE)
1 N9 x- _# f0 b' g$ J8 S
& X: o& l0 w. ?% I  w+ y; T外部高速时钟信息(HSE)可以通过两个时钟源产生:
3 S' W! [" E  M& u. [+ v- @1 C, ?$ m7 \% ?! a1 L* ?
① 外部晶体/陶瓷谐振器
# d+ f0 }6 J3 Q6 {$ K9 U$ a5 ~! O* ?9 P& x" r) j
② 外部用户时钟! C8 ^/ o& j0 \+ m' }0 b
5 O- z" T1 X- J% }$ \$ ?
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
- a7 j$ D; \/ G0 N' i) @
3 [% W* r$ L# c! ]; k" D
▲两种时钟源接入示意图
" ~' ]- M0 q7 k$ m8 {8 P
3 l9 }: a! @: M) E2 a
% m- |7 c! ?  K' o" U8 e03 主锁相环时钟(PLL)
" O5 S  m; D2 O1 W$ Z: S( m3 S- @
STM32F2xx具有两个PLL
1 R' L3 S9 s) n0 @! K$ o/ R& F+ j' g, e( Q
① 主要的PLL通过HSE或HSI提供时钟,并且有两个输出时钟;5 y9 `0 t9 |$ _% H

9 [4 z4 n$ g' Q$ G' T2 K② 专用的PLL(PLLI2S)被用于产生一个精确的时钟去实现高质量音频效果在I2S接口;( i/ i3 M1 X: j/ }, Z4 A

9 k/ B- s" I$ _; ]: q
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
% n' W: q( k: b: j6 L( I
. a4 F# j9 k3 N  C# @

0 V- i% s( T1 [# M# qHSE/M*N/P得到PLL时钟
8 [- w7 N) y' N
& S: V& L6 [- w1 \) M( s3 `! X" j关于PLL锁相环说明, h6 d& V+ B, K# {# l

: Z7 O' f9 z% G; w
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

6 p" X- o$ m1 I7 L* h# e1 ~1 W5 e# k! f" P

$ P  b$ L& a2 F0 \5 ]从1处输入,3处输出是1的N倍。
) l6 _4 @$ @) `: u: _5 |
1 K) V% W$ F' N8 s3处除以N又作为输入,当1和2的频率一样,就锁定了。(之所以图上是xN,因为从2看向3的)
, q0 T/ K1 {# g. j+ N4 \: j- b; R. w8 r3 W- T  a7 z5 `% a

' `* ?" U6 E, \
( [" j$ Q0 u* M- g# n4 M$ d04 低速外部时钟(LSE)) z3 b/ M  d3 R; h

% q3 k7 ^2 L6 X# u; T  CLSE是一个32.768KHZ低速外部晶振或陶瓷谐振器。
3 W, p3 o) \) ]% N6 F& x- F" e/ z6 o3 R- r+ i1 f% p5 V( P
它的优点:提供低速但是高精度时钟给RTC外设,为时钟/日历或其他时间应用。
" u( P2 D6 ]4 x4 F* o
9 s  O( v% r- |3 n3 g' W- o: _" \; f! C! S3 @: n
05低速内部时钟(LSI)6 Q( X5 B) K4 L0 N6 D3 s
1 P2 v" F9 O9 I' w* ?
LSI RC作为一个低速时钟源,它可以运行在停止和待机模式中给独立看门狗(IWDG)和自动唤醒(AWU)。它的时钟频率在32MHZ左右。
0 i$ o/ `8 t' B7 p7 Z
- B1 z  P2 e8 [( X/ G, b: q/ p5 B02、代码分析, V# p% O: P" q1 p- K) r
时钟初始化代码在system_stm32f2xx.c文件中,大部分时候我们不需要修改时钟代码的,各个总线的频率我们可以在文件头看到。8 k4 _4 J. p( N" x( B5 _' j; |- W; s  N
; j# Z- _; O1 {3 ~7 s1 L, M: G
  1. =============================================================================
    & }" f  B; ^/ l! {  @$ c
  2.   *=============================================================================
    ; \( |. K- X& {& E/ h  L' y; k( l) r
  3.   *        Supported STM32F2xx device revision    | Rev B and Y2 o0 a2 V) B; J' |4 W, e7 x
  4.   *------------------------------------------------------------------------------ ^. R' N; b  U9 y# P
  5.   *        System Clock source                    | PLL (HSE)
    % j- G0 V: M/ u: E- X; U$ Z
  6.   *-----------------------------------------------------------------------------
    8 R7 b. i. O3 E, l+ L
  7.   *        SYSCLK(Hz)                             | 120000000' S+ |3 d( W( E1 E6 U, O& V* t
  8.   *-----------------------------------------------------------------------------
    ) @' L8 ]$ E8 b7 W7 h
  9.   *        HCLK(Hz)                               | 120000000
    7 G4 C) t' `  V  W
  10.   *-----------------------------------------------------------------------------
    5 {% P' D* e; U
  11.   *        AHB Prescaler                          | 1, P% D* j1 ?5 U+ p% @
  12.   *-----------------------------------------------------------------------------' n  p6 x+ @. w* ]$ C
  13.   *        APB1 Prescaler                         | 4
    6 i* c/ ~' d! m: p. F9 m
  14.   *-----------------------------------------------------------------------------) x( l. e% C+ U3 O6 Y$ T2 z
  15.   *        APB2 Prescaler                         | 2
      p2 [9 U; w7 d2 A+ X  X
  16.   *-----------------------------------------------------------------------------5 j/ I0 q# k& V. `8 K
  17.   *        HSE Frequency(Hz)                      | 25000000) ?* k( L: U2 W7 f) u. @
  18.   *-----------------------------------------------------------------------------5 p& L/ Z: r9 J8 A: a8 h
  19.   *        PLL_M                                  | 25* {3 G$ g4 E' m$ G& t
  20.   *-----------------------------------------------------------------------------3 p! P& `/ B; V2 s$ v$ L9 w# i
  21.   *        PLL_N                                  | 240
    - v( G( D9 x, Y/ Z8 P- Y* y
  22.   *-----------------------------------------------------------------------------
    8 I) o7 m* G- R* d+ k: k# l
  23.   *        PLL_P                                  | 27 W4 [5 h' E! s% y
  24.   *-----------------------------------------------------------------------------
    # M6 {+ ?0 C* c" Y
  25.   *        PLL_Q                                  | 5' k( p% `1 s( _8 o; x
  26.   *-----------------------------------------------------------------------------
    6 `+ a0 t# T# Q$ N# t
  27.   *        PLLI2S_N                               | NA$ g3 h1 E  T, J8 g3 j
  28.   *-----------------------------------------------------------------------------! v- O) g! T& S( z( u
  29.   *        PLLI2S_R                               | NA
    ! K6 B0 ^. e" ^9 L  e9 a
  30.   *-----------------------------------------------------------------------------
    ! g; k! @6 X2 m. v5 }
  31.   *        I2S input clock                        | NA
    * ^$ ?0 ^0 Y: O$ y3 Y0 Q
  32.   *-----------------------------------------------------------------------------
    : H7 x, M" R1 w& y% {
  33.   *        VDD(V)                                 | 3.34 V4 @* H' J8 a9 _% C
  34.   *-----------------------------------------------------------------------------& X1 h' v7 ~5 x( A9 _- A
  35.   *        Flash Latency(WS)                      | 3
    ! h3 B6 J& d+ s7 z. Y; m7 W
  36.   *-----------------------------------------------------------------------------
    1 {/ G2 G/ R( f( `) {4 L
  37.   *        Prefetch Buffer                        | ON
    5 W& g+ H* Z2 {7 L
  38.   *-----------------------------------------------------------------------------/ [! \  r$ L7 ]/ @' K
  39.   *        Instruction cache                      | ON
    * P. W3 W% D' I9 p! @
  40.   *-----------------------------------------------------------------------------' H0 z& a. J* a2 d8 I
  41.   *        Data cache                             | ON
    8 l% B, @9 D0 g& d- Q  G2 v0 s
  42.   *-----------------------------------------------------------------------------6 w; Z: w) P. P; }0 U& U7 q2 g0 R
  43.   *        Require 48MHz for USB OTG FS,          | Enabled% V( p9 f5 R( m/ O1 X
  44.   *        SDIO and RNG clock                     |
    ) W+ _$ _4 e2 @; @# c  ?
  45.   *-----------------------------------------------------------------------------
    % X' ^; f8 S- B3 B( F. s% b0 J
  46.   *=============================================================================
    * x" |, F, _+ B7 [' `/ G
  47.   ******************************************************************************
复制代码
在文件开始定义的有系统时钟频率的全局变量SystemCoreClock,其他地方需要时钟频率,可以直接使用该变量。
  z9 L. K7 T3 Q7 a9 q3 n% v
  1. uint32_t SystemCoreClock = 120000000;
复制代码

3 e/ M" t$ u- {时钟配置从SystemInit函数执行,调用SystemInit的在汇编文件中startup_stm32f2xx.s(Keil编译环境)。
7 O3 M7 s0 i6 Y6 L5 @, D: \4 F
" A! `" M2 Y3 h8 |$ d
  1. IMPORT  __main- J; q6 P5 o/ r" f' M4 Q
  2.     LDR     R0, =SystemInit1 k9 J' z0 ?& J
  3.     BLX     R0( }3 O" w/ B! e. q. w
  4.     LDR     R0, =__main* z' @" z8 }, Q8 M- j# \
  5.     BX      R0
    8 p0 w. U: w( @5 v: V+ E
  6.     ENDP
复制代码

' i8 \6 N4 U' D. {在这里说明一下文档版本的问题:) k9 Q2 j& r8 x) j  f
& V1 p# }( x, Z8 j' z' _
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
8 N. _' [1 R! X

- ^5 \. q( t( T' H+ d) x▲STM32F20X_User_manual的V7版和V8版对比图
) g; ]$ g7 z9 n9 d. }1 H# v6 D
6 c, r0 b4 c7 K# ]; K+ _" E上述两图的区别是系统最大时钟从120MHZ变成了168MHZ,我的理解是同样是STM32F20X,ST由于技术进步或其他,使得新版STM32F207芯片超频支持168MHZ。: y  ^9 X( f, {, z/ F8 a

" l$ W* i# K2 }* Q5 g下面我们主要分析SystemCoreClock的120M时钟怎么从一个外部25MHZ的HSE得到的。
7 t& C4 Z/ u% ^$ P' J2 a% u6 L+ L$ v: H; Y( P
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
, e' }  g4 [, G$ ^4 Y
/ w% Z$ z) c7 |/ g: \
我们要从25MHZ的外部时钟得到120M的系统时钟,需要上图中标注的重要4点:* u/ g" i5 C* _7 K; H' R6 S! x  ~

! b3 M$ c* V/ R' M; l7 j, U) C1、使能HSE
3 ]8 M* [- Y! \
' Q2 W8 }8 o" M- l( E& g& z0 @2、选择HSE作为主PLL的输入时钟
) Q9 n9 \" R0 E+ ^& b! a
' S9 u- d2 A6 P3、主PLL倍频后得到120MHZ时钟; u+ K, Z1 O" x- o

) p+ y; k$ X9 J2 _5 p# T$ R; V) V$ J4、系统时钟选择主PLL时钟输出作为系统时钟2 q4 J  P1 H% w* A4 v9 M& i: u

: m# }1 w8 o( G我们找到对应的代码
- p. f& z& _. ]8 @: b5 j) H9 ~- X! H4 o# l5 X
  1、使能HSE
4 Q, G! T: g! n9 ~# r3 J; J
  1. /* Enable HSE */6 |( D" c) b# O" Y  d' c0 a
  2. RCC->CR |= ((uint32_t)RCC_CR_HSEON);
复制代码
! P. V( \& x/ @  z% L+ P
在RCC_CR寄存器(RCCclock control register RCC时钟控制器)中,有打开HSE的控制位
( W1 n& z; Z2 T6 |8 ]8 c
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

% L1 T3 c0 v' a4 T* m- b6 S
; l2 J! M. S) d# e$ d: [5 k2、选择HSE作为主PLL的输入时钟+ F4 @+ f* b6 W
  1. /* Configure the main PLL */& j1 N0 d5 D# v5 q4 L; ]3 N4 q
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |/ L& v) S- \* k! [
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码
# h  d# ?; x+ {/ X
RCC_PLLCFGR_PLLSRC_HSE就是配置HSE作为主PLL的输入时钟
: ~# f5 N% M# Y( I3 O3 Q9 {/ ]
7 u. k- S+ Y4 E6 u9 l4 r/ l  3、主PLL倍频后得到120MHZ时钟
% }6 k# V( s9 a5 E5 b' g
  1. /* Configure the main PLL */
    ! `' K! o7 f1 p3 G) \
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
    / X, k/ X# N2 z& R" B" ~
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码
8 x* z1 u! j( ?6 B9 ?& p
4、配置主PLL作为系统时钟的输入时钟
) W+ X9 V& b8 f$ v9 E# o% Q
  1. /* Select the main PLL as system clock source */! [, x) C) x7 l
  2. RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));  R3 I+ e5 [4 K* E! E7 W
  3. RCC->CFGR |= RCC_CFGR_SW_PL
复制代码

. w' \; B& a8 g) g; @对于主PLL的配置寄存器,在RCC_PLLCFGR寄存器中有说明; Y8 g1 @, i! W

' T+ \- n+ o: f  [
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
( t) L- c( t5 P5 u& Q7 I
9 Z  c( r1 @0 d9 Y- g* R
整理后得知f(out)=f(in)* N / M / P
: e; Z1 E/ ?! ^" Y8 F7 F8 E
  1. /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
    # |) t) n  C* r- `* I
  2. #define PLL_M      25
    ; m( u) l6 B, i- t3 [( D$ H
  3. #define PLL_N      240
    , [- q* M$ i: I, m
  4. /* SYSCLK = PLL_VCO / PLL_P */
    : m! U8 I  X  {8 e
  5. #define PLL_P      2
复制代码

5 Z* ?/ s* b! A5 p# M. O: J这样就获得了120M时钟
: D3 t! ~* g) z& a. Q+ V) O
  j" ~: v; O; A6 Z" c注意:
' [7 d+ x4 @5 r, ]2 `5 T+ Z' @" G! i+ A6 m' d% F5 d/ m3 ]
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
1 I0 V; v& q# t0 j+ [

- |' X+ y  ~5 ~PLL_M大于等于2且小于等于630 `8 {4 w+ ?5 v0 L( P

# e# n! m  q* |4 }( N% C
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
0 }( I8 P! |! x  i5 c5 s
$ W. M9 ]; g* M& i( L
PLL_N大于等于64且小于等于432
1 V3 s9 |) T, @5 _, Z  m6 u0 H& \. ]" _0 e% v- v% V
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

: I1 T$ \1 M+ t  V' K  p$ [
$ ?1 f  c; I+ {PLL_P只能是2、4、6、或8
1 @: [* F8 D& r2 s3 \+ V" g
. G) |* q( e" p' P$ T但2对应0,4对应1,6对应2,8对应3。
7 c; [9 G$ ?* U0 n" F" K( N% e* q$ d  @& {/ c  ]9 i6 j1 i$ V& `* F
ST并没有使用if或case语句判断,因为对应的数据除以2减去1就是寄存器这两位的值,所以可以按照下面这样写,这种写法值得我们学习。
5 S  k4 |' B# E$ z5 K* t+ c2 Z( O
(((PLL_P >> 1) -1) << 16)# ?" x4 i- C9 ?5 z
其他外设的时钟配置时
; u% J7 y( u8 D4 |; P% f1 B
  1. /* HCLK = SYSCLK / 1*/8 ^# o& t7 U" U& E4 W" E8 T; f# F
  2. RCC->CFGR |= RCC_CFGR_HPRE_DIV1;, _. d, l( @0 f% x  E, L8 {
  3. /* PCLK2 = HCLK / 2*/9 x/ ~7 d/ J/ R' B* x
  4. RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
    . P* P: D+ f/ O9 S. ^' v
  5. /* PCLK1 = HCLK / 4*/
    6 d9 K7 s2 l1 |' p
  6. RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
复制代码

+ T0 Q6 K5 P; d" P03、备 注
( \6 Z% m5 O5 j. @& \
时钟中断+ Z6 u0 u) S, J( O* J
' Y% `: R8 C! D4 l8 m. }* }4 g8 \
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
) C. o% Q3 r: x0 {

* ^) @8 D1 T+ f1 X4 x可以配置外部晶振出错时的中断,还有RCC中断,因此我们可以在外部时钟出问题时,切换为内部时钟,不至于整个系统挂掉。具体见ST给的官方代码。
+ S' J) @- B( }* {- p& N
" K: I  z% i0 P4 X* u$ g 无源晶振不起振
6 Z+ u# n8 w' s; w- v( c! }& P9 R
! U. Z# S; e0 z/ m' h' ?没有程序,无源晶振是不起振的,需要配置RCC时钟控制寄存器的HSEON位打开或关闭HSE振荡器。具体可以看之前的文章《晶振原理解析》。+ @4 |* z* @" Y4 n) @+ E( [: ]6 _

' u5 i6 i2 e, Y; }1 { 关于APB和PCLK; v" k) u' h- C" C4 D9 o

4 v- I: i2 y' M8 M9 v& w" {. u, QF207是时钟图没有显示PCLK1和PCLK2,应该就是APB1和APB2
( @& S6 h4 m; Y' _; H3 w+ \8 Y1 c( W! [) N  f( A' R
应该指的是一个PCLK应该是PeripheralClock的简称,看F105手册
, t1 O/ y) l4 E" q4 F8 I5 I3 G# E$ M0 E) [" H, ?9 s
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.jpg

/ b0 Z: L* L- J% P+ O0 o; k: @* ~
$ X& f9 y( I- K+ B/ x% `# m& S! c+ p9 q! S2 @% _8 u
& ~( o  m1 |6 b* t1 w' K
: n# {& k7 J$ A6 Q4 U

0 a# f' S6 K3 q% v$ M
/ Z' r7 p/ I4 U" T5 o
6 P0 b9 S0 i6 E: u
收藏 评论0 发布时间:2021-12-3 17:00

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版