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

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

[复制链接]
STMCU小助手 发布时间:2021-12-3 17:00
板子使用的是25M无源晶振,下文将介绍STM32F207的时钟系统如何将25M晶振时钟转换为120M系统主频时钟的。
* N5 _/ s' z( {5 j3 M! [5 M/ W7 j- R& |& q6 J+ I# R. c
01、时钟系统介绍
! d7 M' d7 X, v/ {% n
  z1 G* X( G' p$ E8 k' o
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

+ s2 H1 z0 {1 j7 v. N+ L8 a                                                                    ▲时钟系统专业名词缩写& p9 B- k  q/ Z( g# j" ^
$ n, h+ S, K9 X+ Q
时钟系统关键组成部分! l. b3 i) Z! L

* \' O& Q# k' I01 内部高速时钟(HSI)  K( N. D6 ~' a- I5 w, @/ I" A5 D

% Y, S9 i% Q: ?2 n8 |HSI时钟信号可以通过内部16MHZ的RC振荡器产生,可以直接用于系统时钟或者用于PLL输入。/ `$ c0 `& Z) P  z0 w, `9 ^& ^
/ O' ]  ^% {9 R$ N. P
HSI的RC振荡器的优势是:在最小成本(没有外部器件)情况下提供一个时钟源。它的启动速度要比HSE晶体振荡器更快,但是即使校准频率后,它的精度仍然小于外部晶体振荡器或陶瓷谐振器。
" a# _$ q( G5 `: C+ N* x8 k) H- C
" q) H) V8 L& M6 w4 E9 V- |02 外部高速时钟(HSE)
8 l: S, W, I0 C: C# f/ ^8 G1 Y% V; X4 X- L7 q
外部高速时钟信息(HSE)可以通过两个时钟源产生:
, V8 t' P; V. Q5 a: ]1 C8 ?( Q2 U/ N: h2 Z& w: X* K
① 外部晶体/陶瓷谐振器6 f7 x/ I! ?" r, I# d

3 c; |4 u, f+ T& \+ e* J② 外部用户时钟
$ w' p! c8 S* c( C+ O+ r
/ B% `$ Q. ~6 R% k/ |$ x& h
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
) }( R! M& U0 N7 K

; _; t# T) i& a( L+ @" a9 e▲两种时钟源接入示意图
2 v- C$ u! z4 @7 X- R7 S* L! U* k- K! L

- f+ x# E, e8 f, H7 d* w03 主锁相环时钟(PLL): _# y  N$ g  l' k; e
; K/ y# A3 I. R! C
STM32F2xx具有两个PLL# r' b/ d! x# V8 G6 o$ [0 E
. {, L+ G1 R7 t6 u3 l: O& Y
① 主要的PLL通过HSE或HSI提供时钟,并且有两个输出时钟;
, E# J6 y* Y) ~% o
) Q* f$ {5 R+ h5 N5 v. @② 专用的PLL(PLLI2S)被用于产生一个精确的时钟去实现高质量音频效果在I2S接口;
# g! w. g; Z4 S( P1 {; ~6 B( L7 x' N  {9 M- x" T/ V+ d
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

6 k3 b7 c; d8 t4 `/ F: c
+ H! Q. f3 U2 Y$ C! E: g* \0 [9 G
/ a  W! Z4 O& W" l$ KHSE/M*N/P得到PLL时钟
1 E: h4 B+ G5 N% G+ [2 z, c7 x* I
- `! ^- p  f5 f/ M( P% n关于PLL锁相环说明& {) Y3 f: N. d/ q/ |
" _" L0 X# _7 e" a: ]
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

# x7 t5 r3 N; U4 y
- ~* Z2 i! v& ^% |# Z0 Y9 o4 N  J
) u- j3 J4 I) e2 N# x( e从1处输入,3处输出是1的N倍。3 m/ W6 s/ D/ V$ t5 U
; i3 F/ X/ m! w5 [/ r4 {
3处除以N又作为输入,当1和2的频率一样,就锁定了。(之所以图上是xN,因为从2看向3的)
" |9 I' L( Y1 ~( j% p) l
: `, S9 J  ?7 n) T: t# Z
. O" E3 |( n' c, R  H+ C8 u
, T* L8 w8 @) z/ M, ^$ ?/ T04 低速外部时钟(LSE)- n% L4 {( _, s8 n, }, y0 G( H
5 V6 p+ L# w; ?2 y
LSE是一个32.768KHZ低速外部晶振或陶瓷谐振器。
" I0 k/ b0 m& T; e4 k6 ?( S
, s3 q) U; U0 ~- u' k, n( A( n8 b, ~它的优点:提供低速但是高精度时钟给RTC外设,为时钟/日历或其他时间应用。* Z! f# \9 m$ B* I8 S5 I0 l* p

5 y& S8 W! F# w: V6 i+ O% d% S+ p# d( E1 _+ d! e7 E
05低速内部时钟(LSI), M$ ~3 |6 V! k  \7 h: w

  E$ I1 ]: i( D$ ]: X( H4 rLSI RC作为一个低速时钟源,它可以运行在停止和待机模式中给独立看门狗(IWDG)和自动唤醒(AWU)。它的时钟频率在32MHZ左右。
0 J5 n1 q  T4 \4 h- Y& z
* e0 U8 [$ x$ o! a+ G) w02、代码分析5 d) T8 t% r7 x: h3 g0 ?
时钟初始化代码在system_stm32f2xx.c文件中,大部分时候我们不需要修改时钟代码的,各个总线的频率我们可以在文件头看到。8 G- i* t3 E. C& q: }

! C1 e2 E4 Q* W1 j' _9 u7 p
  1. =============================================================================
    8 O% j* J* T$ e$ c2 q
  2.   *=============================================================================$ w) y, X- }' ~6 V) U' h: O- H1 J5 F
  3.   *        Supported STM32F2xx device revision    | Rev B and Y
    ) r# ~0 x: J. K3 s
  4.   *-----------------------------------------------------------------------------
    & f! x. r& u6 D9 Q9 f3 `% r
  5.   *        System Clock source                    | PLL (HSE)
    ( f$ }5 {( l+ r% [7 t
  6.   *-----------------------------------------------------------------------------
    % q' g: z2 F  O2 S
  7.   *        SYSCLK(Hz)                             | 120000000
    " Y) l* ~1 A$ \/ w$ Q
  8.   *-----------------------------------------------------------------------------) y  b: M: [) [: L; w% T( _
  9.   *        HCLK(Hz)                               | 120000000
    3 ]9 `+ u( Q/ A- J8 r5 N% {
  10.   *-----------------------------------------------------------------------------
    3 W& K) z6 |4 |; R3 [! T5 m
  11.   *        AHB Prescaler                          | 1
    2 x3 u9 J2 ], t- o; Y
  12.   *-----------------------------------------------------------------------------1 g2 }% K! X1 O' c1 o
  13.   *        APB1 Prescaler                         | 4
    7 I! u6 k5 F3 P, z
  14.   *-----------------------------------------------------------------------------
    ' W$ g+ ~7 u) f
  15.   *        APB2 Prescaler                         | 2; z' ~4 M' D+ u( V
  16.   *-----------------------------------------------------------------------------$ C, ^3 E* t8 y, @# j3 ^4 S: S
  17.   *        HSE Frequency(Hz)                      | 25000000
    2 ^. F( ^$ F9 p+ \1 ~3 Y
  18.   *-----------------------------------------------------------------------------
    5 e  ^; N8 _5 e* I* c
  19.   *        PLL_M                                  | 258 M: w9 P/ f, N- \
  20.   *-----------------------------------------------------------------------------" e( P& o9 T( j6 _2 P% F
  21.   *        PLL_N                                  | 240
    * ]0 ?: g) p/ V' I9 v0 q' a$ Q- H
  22.   *-----------------------------------------------------------------------------  N- n! k' a2 t! w' K
  23.   *        PLL_P                                  | 2
    4 x% C% Y  ~+ }/ l7 o2 n2 _
  24.   *-----------------------------------------------------------------------------4 X; Q7 R2 h& Q5 ?/ Z" u, Z
  25.   *        PLL_Q                                  | 5
    & U# i+ C7 s9 @( F6 T# M
  26.   *-----------------------------------------------------------------------------8 L4 j: c! b' ^1 D4 o1 x
  27.   *        PLLI2S_N                               | NA
    5 ~) V7 V0 y  ^  ?' N* y& X
  28.   *-----------------------------------------------------------------------------
    + I# w$ E: J% O6 T7 z7 b
  29.   *        PLLI2S_R                               | NA
    2 B. X4 A0 L; F5 l' Q' u- G7 w8 _- S  R
  30.   *-----------------------------------------------------------------------------, D" k6 `3 i4 R$ p3 G
  31.   *        I2S input clock                        | NA
    , c! P) H- V: [; T% I; b( X( P
  32.   *-----------------------------------------------------------------------------
    $ y6 q& H9 {$ q# |* n8 b* ?8 O
  33.   *        VDD(V)                                 | 3.3
    # q# P; X5 L9 \1 A* q* |
  34.   *-----------------------------------------------------------------------------0 Q9 b9 r( B! o, ?3 Q7 g
  35.   *        Flash Latency(WS)                      | 3
    5 t, p$ k+ z. ]: B; G! W' c, R& I
  36.   *-----------------------------------------------------------------------------0 Z- F5 `2 I7 A1 s. p' ]
  37.   *        Prefetch Buffer                        | ON
    ( I" z! _2 h. _/ e
  38.   *-----------------------------------------------------------------------------
    # e6 {; ?5 A9 [/ g
  39.   *        Instruction cache                      | ON
    ( I+ \) F/ V0 G5 h
  40.   *-----------------------------------------------------------------------------
    * R' T" t. U5 J6 b$ }8 u
  41.   *        Data cache                             | ON7 y5 E8 U  f- r: u" _. e& o+ z' {1 H
  42.   *-----------------------------------------------------------------------------
    2 e0 P4 b6 a6 W4 N/ `9 r0 ~+ j
  43.   *        Require 48MHz for USB OTG FS,          | Enabled" e, ~" C  n" }5 S
  44.   *        SDIO and RNG clock                     |  N7 `/ O% Y/ _/ Q
  45.   *-----------------------------------------------------------------------------
    1 U- l0 l# T* @' U: G0 _% P
  46.   *=============================================================================; s3 n; Q8 C- \/ z+ o" ^
  47.   ******************************************************************************
复制代码
在文件开始定义的有系统时钟频率的全局变量SystemCoreClock,其他地方需要时钟频率,可以直接使用该变量。
7 n9 {1 F& Q7 {" I0 S  x( M% c7 E
  1. uint32_t SystemCoreClock = 120000000;
复制代码

6 C( w) l( n4 `3 C8 k) E2 ]: _5 P时钟配置从SystemInit函数执行,调用SystemInit的在汇编文件中startup_stm32f2xx.s(Keil编译环境)。
1 L+ s' T+ F4 f. e0 B: i3 o0 J# O+ b% n! G1 P0 M% q% u$ C
  1. IMPORT  __main& z* t0 I; X( M  f' R2 S
  2.     LDR     R0, =SystemInit7 v! e  N0 F; O, n
  3.     BLX     R0" S' ?7 Q% R; Z& Z
  4.     LDR     R0, =__main
    + r9 D4 |9 B# F# j& @
  5.     BX      R0
    + Z/ v0 y# E6 u8 T
  6.     ENDP
复制代码
9 w0 r9 w* \' I' Z# P. Z
在这里说明一下文档版本的问题:2 b0 _% Q% X, e6 Q" P' u
4 n! {0 [3 ^  ]2 Y( _& K
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
8 _! Q  F# _8 _) K8 ~/ y) k

3 w+ V( K; Z2 ?$ }▲STM32F20X_User_manual的V7版和V8版对比图
  B9 S1 f; r. o% |1 C( g# [2 P0 |3 N
/ _2 p( c( K/ ^" |) `上述两图的区别是系统最大时钟从120MHZ变成了168MHZ,我的理解是同样是STM32F20X,ST由于技术进步或其他,使得新版STM32F207芯片超频支持168MHZ。
6 Y2 X* M: @, K' ^6 v7 f8 h! E0 ?9 \# }/ r
下面我们主要分析SystemCoreClock的120M时钟怎么从一个外部25MHZ的HSE得到的。
$ W& s# M  C: K) p8 t+ @6 x7 |9 t- q: ^. `. e+ ?( Y
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
! ^& |* X& q4 }: g2 J5 R: i

' N) Z2 \% X, r& e我们要从25MHZ的外部时钟得到120M的系统时钟,需要上图中标注的重要4点:
5 R8 N' I0 K+ A2 `2 Q5 T0 ?5 A  P: @1 v/ c  T
1、使能HSE' @  q$ Y# u; V3 X# I+ P* S

5 E7 X! K5 C' S" ^& J1 g  K8 s7 H2、选择HSE作为主PLL的输入时钟
+ {+ G4 A: l5 Q2 z" q# d6 L% @: p/ x7 y
3、主PLL倍频后得到120MHZ时钟0 p8 I- d1 S% `* ~+ Z
+ _9 w# a% c% \4 `6 Y* }0 V
4、系统时钟选择主PLL时钟输出作为系统时钟
; c8 J- j  T& g" Y
& V5 j1 R, K0 \我们找到对应的代码- ^4 S5 r/ E8 C2 K3 |; i
3 r" x! e/ M7 n# d
  1、使能HSE+ `; K7 t& G% Y5 {# S5 R1 x
  1. /* Enable HSE */$ n/ w' K& B: }6 P7 C5 R" k7 n
  2. RCC->CR |= ((uint32_t)RCC_CR_HSEON);
复制代码
+ I$ V: L8 v+ o; q
在RCC_CR寄存器(RCCclock control register RCC时钟控制器)中,有打开HSE的控制位
( P" }0 F* _" C$ \# S# s# ?
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

2 t" \2 b' J; U9 L, E1 A' F! }$ T, b2 J$ R& S
2、选择HSE作为主PLL的输入时钟- d; m* h. d5 @- H
  1. /* Configure the main PLL */# i) b" N7 q1 u# m- X" g+ i! ?( A
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
    2 f3 m# t3 l+ f, O) _8 H- ^
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码

8 _$ R5 X$ g0 ~RCC_PLLCFGR_PLLSRC_HSE就是配置HSE作为主PLL的输入时钟: b- p; ^, j: n, u. Y
# C, i; o2 U& q+ f
  3、主PLL倍频后得到120MHZ时钟0 T. {+ [7 o3 n  A! n( ]
  1. /* Configure the main PLL */( c  l2 {3 N7 G$ s
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |- p  L9 ^, y6 H) w: e
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码

+ m& o/ p" c& K7 w: O4、配置主PLL作为系统时钟的输入时钟# O, s+ \5 \# h3 a5 m3 U+ e2 R
  1. /* Select the main PLL as system clock source */
    1 j; C/ G7 g+ P, f6 @4 e- Y4 x
  2. RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    : c$ ^8 J4 z1 o0 f6 Y0 a2 v$ _1 l
  3. RCC->CFGR |= RCC_CFGR_SW_PL
复制代码

' J$ [, H7 m$ I4 R' [+ s对于主PLL的配置寄存器,在RCC_PLLCFGR寄存器中有说明
5 V: E( J' E8 m8 l8 W$ Y4 N  g! S( ~0 T6 ]
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
" j/ Y$ K, ?2 e3 L" k, s6 o
4 R/ y. ]% d; `0 c5 h; A) |
整理后得知f(out)=f(in)* N / M / P/ D7 j; z" r. v7 R) f; o
  1. /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */$ Z8 I" z) Z" _7 v5 y. w- {
  2. #define PLL_M      25: t! f7 \) v  |' D% y$ ~
  3. #define PLL_N      240' K& s! O$ f  P+ ^
  4. /* SYSCLK = PLL_VCO / PLL_P */+ @) e( R# N. V: x
  5. #define PLL_P      2
复制代码
. {8 D9 W; k9 @6 g4 Z
这样就获得了120M时钟1 V9 @, u- X4 T
( C6 M: c) m# U, S8 H
注意:% i% v" a1 g7 S: o$ V2 \$ J
: [# D' ?7 ~/ v1 P3 B! H' N
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
5 d9 A: B" C7 F; w- J% \& I' g$ H

( w+ q& @& d, L8 rPLL_M大于等于2且小于等于63
5 L- ~: c. q; I2 u. x8 Q, h* ]( V9 D1 d9 b7 i5 M/ X
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
# T) ?. u5 }/ j. N+ m  r
, f- Y: n) s5 I! v: i
PLL_N大于等于64且小于等于432* Z& {" q6 S5 Q+ K- A2 `( Y
7 |! y7 |0 ]3 Z2 z/ A
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

9 I) h  w" U# Z& O. G
) O* d% @9 t; L. bPLL_P只能是2、4、6、或8
- z8 Z/ l6 J0 G) [3 X3 ^  @# e# t* t) b+ X
但2对应0,4对应1,6对应2,8对应3。
; v2 x/ c0 V0 H' Q9 P8 Y
: m- r: y( ^9 l; A) BST并没有使用if或case语句判断,因为对应的数据除以2减去1就是寄存器这两位的值,所以可以按照下面这样写,这种写法值得我们学习。
) [3 t* S( N, s) A, N' f0 Z9 z( E7 b; i0 p/ E( Z7 X' L: r9 B% f! `" F
(((PLL_P >> 1) -1) << 16)6 I$ C/ t4 P2 d% X- ]* ?6 k
其他外设的时钟配置时5 K. {$ N: F) i: h2 k  m8 P% L) d
  1. /* HCLK = SYSCLK / 1*/
    % S0 b, A4 _1 M
  2. RCC->CFGR |= RCC_CFGR_HPRE_DIV1;- }1 F9 K: Y! O* h% w5 w
  3. /* PCLK2 = HCLK / 2*/
    " C  T/ b, v% a8 |* f, M) C: O
  4. RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;# Z/ E2 |3 T, h: Q( u+ y
  5. /* PCLK1 = HCLK / 4*/* w0 O9 r3 g8 P. p+ f
  6. RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
复制代码

, {1 ^8 i, H) P) H2 w03、备 注

1 R9 B6 t+ Q. ~7 G- Y时钟中断
: W# n  M' N9 k! k5 M0 M
6 L! j1 \# i6 J" T$ [1 D+ p
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

; G. U3 r! k* l3 `4 B1 R
; Z0 h2 ^! A4 |0 U2 {可以配置外部晶振出错时的中断,还有RCC中断,因此我们可以在外部时钟出问题时,切换为内部时钟,不至于整个系统挂掉。具体见ST给的官方代码。# x- w. A  f# Y

  @. b% h( {* K 无源晶振不起振
- q& g6 H  b, c" }4 K
- q* N" j; o: j0 P3 {- M+ g没有程序,无源晶振是不起振的,需要配置RCC时钟控制寄存器的HSEON位打开或关闭HSE振荡器。具体可以看之前的文章《晶振原理解析》。! j# m5 T( W' q% r
: a: C1 l- S4 n( c+ O8 R
关于APB和PCLK. ~! z/ r! S1 e& S  Z# A3 u9 H
# T; D9 a9 h( ^6 ^% Y) W9 ^
F207是时钟图没有显示PCLK1和PCLK2,应该就是APB1和APB2/ \; f& }) c: K, [  K* ]4 M

/ g- {( \! ?# E, U$ U" x7 O& \! Q应该指的是一个PCLK应该是PeripheralClock的简称,看F105手册4 R3 v. G  o8 L5 w9 z7 Q

) g3 |* s# m0 T
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.jpg

) U% s4 h  f) P/ C6 y* W4 ^6 b, T+ {" c
5 ?. J3 m  o: ^9 i/ J
2 C+ K6 G" c( Y3 u. P

, f4 _2 N7 @: J& X% T4 A% I6 d1 n9 ^/ r

4 ?1 U* ~8 I8 s# M8 o
& G8 S% ~; b5 T
收藏 评论0 发布时间:2021-12-3 17:00

举报

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