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

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

[复制链接]
STMCU小助手 发布时间:2021-12-3 17:00
板子使用的是25M无源晶振,下文将介绍STM32F207的时钟系统如何将25M晶振时钟转换为120M系统主频时钟的。
# o2 n$ C% M7 u+ [! y# B0 ~" N7 D0 x# n+ i& d2 J
01、时钟系统介绍
$ L6 u. P" e. j& |' ~3 B- p; ]0 {% K) q1 L. [# v
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

3 z. T2 [, m; @: r8 Z                                                                    ▲时钟系统专业名词缩写
+ K8 Z5 U0 \! ?+ s, e2 ]
+ A4 v- }3 v$ d. H0 x时钟系统关键组成部分. T) Z0 X/ ^& p* z

' Q4 S; z4 u) q9 f# L01 内部高速时钟(HSI)* N: R! ~% \9 W) R+ Z  l

" m1 z, s3 q$ B, i* B0 j% T* n) s2 iHSI时钟信号可以通过内部16MHZ的RC振荡器产生,可以直接用于系统时钟或者用于PLL输入。, i. a. C- |4 O* ~( g( a
$ B% Y9 I8 B; M2 h
HSI的RC振荡器的优势是:在最小成本(没有外部器件)情况下提供一个时钟源。它的启动速度要比HSE晶体振荡器更快,但是即使校准频率后,它的精度仍然小于外部晶体振荡器或陶瓷谐振器。' n/ ]% K0 d4 S  _2 s

% ~( b6 ]# {4 O* R, c7 c6 P02 外部高速时钟(HSE)9 p  B; i1 I7 C9 j3 b8 O" z
  h5 F- e" D4 O' L8 \" B+ r
外部高速时钟信息(HSE)可以通过两个时钟源产生:9 k5 a, J- H1 O

8 j6 A8 ?- l4 w5 s  [0 ?# j) S① 外部晶体/陶瓷谐振器- @# f4 z0 f$ v7 k
' p# j. {. a- c% s; u3 V
② 外部用户时钟
- b* g- n  Q# q6 B8 ?& [/ E2 X' O
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
: j. b9 J. t; w! J( a

/ A6 F& Y" U- O, S9 g▲两种时钟源接入示意图- j" T# f0 }3 B

  `) a: Y4 w; D9 ~+ \
; k4 K( `& U' E8 b& y$ @03 主锁相环时钟(PLL)% x; E* M5 `/ x8 J
, _! C, }& l2 [4 @- ]
STM32F2xx具有两个PLL
1 o9 q( a" i4 m. e' `, B( n& K0 p' u/ S" W! L
① 主要的PLL通过HSE或HSI提供时钟,并且有两个输出时钟;( t6 o0 V( B! e4 b: j

5 z7 b6 p1 J+ l) d② 专用的PLL(PLLI2S)被用于产生一个精确的时钟去实现高质量音频效果在I2S接口;% ~( {0 P& s) H  I/ }

; v& ?; y8 B  P& [2 c, y8 Q$ B
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

  T2 x6 x# X4 X' w! l  _# p$ D
- W! D( g, D5 d9 W( E  A) v* j' d  y$ w+ d4 E
HSE/M*N/P得到PLL时钟' M3 i! Z* n* K% J! @$ T* M4 }* r

5 u! B+ N1 ?; I5 }+ u6 B5 \! d3 G关于PLL锁相环说明
* r0 X2 ?. p( \! V# l$ s. v, e& M" B' F. V) I' E# }; M) K5 b
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
, X* j6 Q. V6 s- E1 M
# a' ^1 Q, H4 g& r* o

! q# J. ~9 ^" [* Y- B. L& b% s从1处输入,3处输出是1的N倍。
8 ?" i: s! b5 l3 I: P8 G2 o, A$ E5 ~8 O& y) H* e
3处除以N又作为输入,当1和2的频率一样,就锁定了。(之所以图上是xN,因为从2看向3的)+ P" j( l& H* A& S  W; ?
& D+ C2 y$ n/ e( D" `1 U" ^

) V; S6 V) ?; m4 R$ ^$ a; o. J) T5 }+ m# y- o
04 低速外部时钟(LSE)
+ M9 S7 k' B2 S1 Q5 N2 s4 G+ c7 T
  N$ d. n* N/ Y3 \1 N: J  _LSE是一个32.768KHZ低速外部晶振或陶瓷谐振器。
. ]& u* @; F; Z. l: f
8 n- u% h: [1 }' y5 X它的优点:提供低速但是高精度时钟给RTC外设,为时钟/日历或其他时间应用。
6 K4 n- c! `" }, n# a
% O$ n8 e; r" P/ a5 ]* P9 X+ ~. a4 J6 S! z$ @( J
05低速内部时钟(LSI)! q- |, B5 [# @* d2 L# h: y

* |* N: Y" L. X5 q( ]: m9 V, ZLSI RC作为一个低速时钟源,它可以运行在停止和待机模式中给独立看门狗(IWDG)和自动唤醒(AWU)。它的时钟频率在32MHZ左右。
6 W; s  ], i9 [6 z/ \# `2 P4 ~
! h0 B5 {' Y9 z3 T02、代码分析
& n6 o! ~: D  a时钟初始化代码在system_stm32f2xx.c文件中,大部分时候我们不需要修改时钟代码的,各个总线的频率我们可以在文件头看到。
/ [# w4 x* L) P% O9 y8 h- F- B7 Q8 y6 j- M  a
  1. =============================================================================
    6 b: O. g  Z7 a: a- }+ _
  2.   *=============================================================================: e& s  G- Q0 k" G2 S6 N2 `$ j
  3.   *        Supported STM32F2xx device revision    | Rev B and Y. e4 W( I5 X7 Y$ {  E
  4.   *-----------------------------------------------------------------------------
    ( z0 x, j' {) p4 E
  5.   *        System Clock source                    | PLL (HSE)0 |4 s0 {' N4 M# g0 @
  6.   *-----------------------------------------------------------------------------
    ) [. A6 M1 g- \1 Y) h
  7.   *        SYSCLK(Hz)                             | 120000000! _! u7 k1 c( B; ]$ D% |1 O! d4 I: e
  8.   *-----------------------------------------------------------------------------$ r$ T- p$ s6 Q5 [$ Q- O
  9.   *        HCLK(Hz)                               | 120000000
    / z* u& h- e6 z4 }+ _. o' x
  10.   *-----------------------------------------------------------------------------
    % x$ T3 }* T0 d1 I( x+ q+ b0 G
  11.   *        AHB Prescaler                          | 1
    & R. |" K  N8 o
  12.   *-----------------------------------------------------------------------------8 [" Q0 T  G- r" E
  13.   *        APB1 Prescaler                         | 4  U0 e1 u: N8 Y0 ]
  14.   *-----------------------------------------------------------------------------2 S- j4 b0 S. H6 l
  15.   *        APB2 Prescaler                         | 29 j  y  L5 D; S8 t7 T. C$ G* ?
  16.   *-----------------------------------------------------------------------------
    ! \( e3 y7 I6 q) B3 e
  17.   *        HSE Frequency(Hz)                      | 25000000
    - ?4 K% g8 [  Y, c  d- k
  18.   *-----------------------------------------------------------------------------5 V* E% y2 [* E; ?) P7 j& n6 z
  19.   *        PLL_M                                  | 25
    $ O8 u- v- {. m) `4 R
  20.   *-----------------------------------------------------------------------------
    : c) H% Z. y) _& y% q. H. B
  21.   *        PLL_N                                  | 240
    7 M7 n- T) H# C; \/ i$ b! E
  22.   *-----------------------------------------------------------------------------
    0 L* H7 T) ~7 s- e% C
  23.   *        PLL_P                                  | 2
    ' T  Y& V  v2 f2 Z1 [0 C* Y$ l- O
  24.   *-----------------------------------------------------------------------------
    6 |7 K/ I% h, _
  25.   *        PLL_Q                                  | 50 w3 X1 `/ H% _
  26.   *-----------------------------------------------------------------------------
    0 Y* _9 k) k$ y$ @8 o5 L
  27.   *        PLLI2S_N                               | NA6 }- P4 `, U: S" ~9 G
  28.   *-----------------------------------------------------------------------------
    ' S9 k" |3 \4 a" k. Z
  29.   *        PLLI2S_R                               | NA
    ' f2 H8 n3 d& Q2 U9 p, K1 J
  30.   *-----------------------------------------------------------------------------" b; w% |- h6 I# ~
  31.   *        I2S input clock                        | NA7 M" b2 ]$ m% f9 A. C1 o* K9 E
  32.   *-----------------------------------------------------------------------------6 B6 j5 A4 V" L1 _0 ~
  33.   *        VDD(V)                                 | 3.3
    . j; l4 p" l1 ~. F4 n& v" f1 Q
  34.   *-----------------------------------------------------------------------------' u& }8 I) x! g7 S" @5 ^. ^+ j+ y0 C
  35.   *        Flash Latency(WS)                      | 3
    : N7 Z0 ?" G1 D5 \( c
  36.   *-----------------------------------------------------------------------------
    % U  `0 o& [1 J& O7 g' g+ R9 i
  37.   *        Prefetch Buffer                        | ON
    ; X1 s+ P0 C1 ~; ?8 M" u( t
  38.   *-----------------------------------------------------------------------------
    4 L5 _; _: M9 ?7 `$ Y" k! o( R
  39.   *        Instruction cache                      | ON: s3 Q7 t: |) C4 G/ M7 F/ L
  40.   *-----------------------------------------------------------------------------. g# m+ l$ ], I0 L; O' ]1 _
  41.   *        Data cache                             | ON
    3 L$ N) D& V, B4 a/ g: Q7 c7 m' w
  42.   *-----------------------------------------------------------------------------
    * t- _( t9 E9 B- y. r
  43.   *        Require 48MHz for USB OTG FS,          | Enabled0 u: H* C' `, h4 z
  44.   *        SDIO and RNG clock                     |
    $ k8 v& o% q! O
  45.   *-----------------------------------------------------------------------------/ ^, g8 B% Z$ I4 ~/ h
  46.   *=============================================================================
      Y2 B! M% u, b9 V, r* q
  47.   ******************************************************************************
复制代码
在文件开始定义的有系统时钟频率的全局变量SystemCoreClock,其他地方需要时钟频率,可以直接使用该变量。* a- i. O) L( B' R
  1. uint32_t SystemCoreClock = 120000000;
复制代码
$ d" L9 @) u3 ?. v
时钟配置从SystemInit函数执行,调用SystemInit的在汇编文件中startup_stm32f2xx.s(Keil编译环境)。
5 ], ?" e2 f( n3 J& \" o* |5 R  N: H; g3 C6 y, N2 a1 n
  1. IMPORT  __main5 }7 }7 N1 Z( \5 t" z
  2.     LDR     R0, =SystemInit4 Y) u( \+ ~$ X
  3.     BLX     R0
    % X% W2 y( {# T9 s5 Q
  4.     LDR     R0, =__main
    8 ^7 p: F+ R  y3 ~
  5.     BX      R0
    & T6 n3 R' E2 P( v. x, i  x* m" J
  6.     ENDP
复制代码
% L- U& T. f; h7 R/ d, r" O
在这里说明一下文档版本的问题:
/ G1 w' B& O. X9 Z5 G  }, G1 u* J% H( f! X. H5 _( N
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

& d. q7 g* n3 f  e) M$ T' h5 a9 N3 \! @
▲STM32F20X_User_manual的V7版和V8版对比图1 B* i0 W: w% Y/ ~1 b& R) @6 J
7 }# k8 E# k% [) e% P0 Q( c
上述两图的区别是系统最大时钟从120MHZ变成了168MHZ,我的理解是同样是STM32F20X,ST由于技术进步或其他,使得新版STM32F207芯片超频支持168MHZ。, V. D9 S6 @9 h2 m

, D  x# m9 c" @/ @/ O- v下面我们主要分析SystemCoreClock的120M时钟怎么从一个外部25MHZ的HSE得到的。
; z; R5 V4 b2 G8 q, d& q9 R& x' `6 }* f: c
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

/ V: W$ ^8 k2 t+ x0 |) \; V+ @/ G% Y4 h6 J3 j$ t. R  `
我们要从25MHZ的外部时钟得到120M的系统时钟,需要上图中标注的重要4点:
0 f/ |1 n& E* \. D/ _. J+ [4 D0 ?7 x! u0 _  \! W# Z
1、使能HSE
7 \* a/ N0 g1 C# @, ^  a% h8 L" Y
2、选择HSE作为主PLL的输入时钟' i6 Q' o: t( I+ g0 p0 l
% l7 S: B. C2 W# e1 k% p
3、主PLL倍频后得到120MHZ时钟
, P, j+ q4 _5 k4 b( Z- ^
8 H5 O: k$ D4 W6 ]4 D4、系统时钟选择主PLL时钟输出作为系统时钟% {3 ?/ G9 O: J1 p% [) u- p
7 a3 n: b+ L9 D, R
我们找到对应的代码
" a2 u. ^8 P. \/ s% ?5 g/ k9 Q- [1 s9 X+ U$ p9 v- d
  1、使能HSE8 \& l7 {  o; y' H
  1. /* Enable HSE */9 k! v; I. ]2 _7 s. u
  2. RCC->CR |= ((uint32_t)RCC_CR_HSEON);
复制代码

7 o' m9 M# x* G: D在RCC_CR寄存器(RCCclock control register RCC时钟控制器)中,有打开HSE的控制位3 g, H9 x5 r3 I1 S6 w: a
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

& C9 L1 L1 X: W+ ~! t+ e/ O& u7 k, m5 p1 b. V; f5 ~
2、选择HSE作为主PLL的输入时钟! w1 i8 q6 ]) ?$ X$ X. M" Z6 ^
  1. /* Configure the main PLL */
    % A8 r; s  _8 G" G% f$ q$ @1 O
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |, I% g9 q$ u2 Z; |2 _/ W* @  {
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码

! F/ q: d  G  j  D/ `0 mRCC_PLLCFGR_PLLSRC_HSE就是配置HSE作为主PLL的输入时钟& S! G9 E9 @, Y; l& j
* |1 [4 n) ^3 a! e8 R! \3 j
  3、主PLL倍频后得到120MHZ时钟4 R. M/ _# c  k1 r: h5 W
  1. /* Configure the main PLL */
    , g& j" N" k, ]1 \% h, z
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
    9 F$ H8 b- x6 E- R& E( J6 }) L3 s3 e- e
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码
* F& c/ ]7 o7 V2 u
4、配置主PLL作为系统时钟的输入时钟5 J: s0 m; g( g/ C. S6 r! B
  1. /* Select the main PLL as system clock source */
    ! g& T  W" c3 R$ U! g
  2. RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));5 |! f, p1 Q9 ~; ]
  3. RCC->CFGR |= RCC_CFGR_SW_PL
复制代码
$ X4 z# ?# F8 f9 c7 ?' d( y
对于主PLL的配置寄存器,在RCC_PLLCFGR寄存器中有说明
3 B  @- s! |6 e2 b* w! I! V$ W0 _7 N+ D+ r
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

- n2 m/ [7 _& G* M9 f" X$ r2 t1 i+ `7 A7 |1 \/ }( Z0 U& C8 C2 O5 R
整理后得知f(out)=f(in)* N / M / P  ]# i8 ~/ C( K, t' G; y
  1. /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
    * N( U" k, U* a7 X
  2. #define PLL_M      255 g7 X) ~  }" ^4 T
  3. #define PLL_N      240
    ' C$ J$ S2 B) M& x8 j; k" V+ C
  4. /* SYSCLK = PLL_VCO / PLL_P */
    9 S: D) v# k4 a. I6 i8 L% r/ m+ q- {% M
  5. #define PLL_P      2
复制代码

6 q. [! u: k. y( G/ S这样就获得了120M时钟( j9 ]& ^6 E0 S
3 v0 a$ {( b3 C5 X
注意:% ?* U* {( S/ o9 ^6 w: j) q

- t1 }* k! J3 S" J4 `. g' G! }
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
- c: M) e1 J$ s6 d& W5 C# n0 L

8 P. u# c- A2 j. @0 [# S, h! w/ XPLL_M大于等于2且小于等于63: u/ o3 Z: G/ A5 R- x

- u9 ^5 P; [  D% A6 I7 N, v7 X
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
$ _  e) Z7 O. t% \% D6 V

' e1 `$ K8 f2 O( V% }PLL_N大于等于64且小于等于432
# Z* p3 ^( ^( M) ~6 J' |' F9 g$ G6 ]" k3 f  @# k
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
& T% A4 g% W" e" n; N- W) u& i7 a7 w$ h6 f

+ B# e+ Q& N. N% m- NPLL_P只能是2、4、6、或86 ]! s+ q; k9 p* e. y) K# U) i

. [% K) }1 J' y2 K9 A* T6 A但2对应0,4对应1,6对应2,8对应3。
6 V( `9 {( I" P
3 \% t* d" O7 J2 oST并没有使用if或case语句判断,因为对应的数据除以2减去1就是寄存器这两位的值,所以可以按照下面这样写,这种写法值得我们学习。
, {7 T) R9 k' l  ~- }* B: d3 V- v' Q" D  p8 h
(((PLL_P >> 1) -1) << 16)
2 p9 H9 o" A$ [9 Y其他外设的时钟配置时. Z- r8 N1 z2 s% i
  1. /* HCLK = SYSCLK / 1*/1 x2 E  }1 r8 k3 `3 g4 x
  2. RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
    * Q, {' ^+ K) M9 \# X! @
  3. /* PCLK2 = HCLK / 2*/
    5 B% I9 h1 @0 {0 U; N. r1 \) R7 E
  4. RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;0 e7 P. y' I* J# B
  5. /* PCLK1 = HCLK / 4*/
    ) X3 z0 d8 B: M0 v) ?3 }
  6. RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
复制代码

& `  F0 S" d$ K- e! I6 S# Z03、备 注

5 w9 a  ^( s1 h: V8 ^时钟中断
$ W7 p6 `, z- v" ]9 ?* t: s5 Q0 l" ]9 G& ]+ ]3 M9 A
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
: o& d' V9 S$ s5 Q
0 c$ R5 C; G& c, J9 f2 ^* q
可以配置外部晶振出错时的中断,还有RCC中断,因此我们可以在外部时钟出问题时,切换为内部时钟,不至于整个系统挂掉。具体见ST给的官方代码。1 }8 ?4 }( d+ F0 d; I& j! w6 @; d
0 U% d% L% Z% k3 J# k6 f8 l
无源晶振不起振" r1 g" I) ^7 t3 \5 j

$ A: R4 y) K9 o+ K/ u* |/ N  I7 c没有程序,无源晶振是不起振的,需要配置RCC时钟控制寄存器的HSEON位打开或关闭HSE振荡器。具体可以看之前的文章《晶振原理解析》。4 ?* v. m9 |0 D5 C2 N- ~
1 h; ~. t3 J8 \2 z
关于APB和PCLK$ }/ ?$ b5 B, c

8 J- @# A6 V( u$ CF207是时钟图没有显示PCLK1和PCLK2,应该就是APB1和APB2) A/ b' p' B% R1 Z
$ Y/ T' C  c7 _! I) a; \, m
应该指的是一个PCLK应该是PeripheralClock的简称,看F105手册
; D1 v" Z0 b7 A  G+ w' f9 p( `& ^# v: @6 `
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.jpg

, C6 S7 d$ a1 m& X1 |% e' U
, X, t3 d: O/ q4 `  |# j8 ?+ _2 z* m8 K- A: S( R* W, S

& v7 i, P5 h7 }" T0 Y8 ^
7 G' j5 y( r( s5 _! C9 U$ P8 {
, e6 G0 M4 r' M% ~
, ]. b/ u5 O3 E- t$ g
" n4 u" y7 L5 I: R- Y* u; n
收藏 评论0 发布时间:2021-12-3 17:00

举报

0个回答

所属标签

相似技术帖

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