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

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

[复制链接]
STMCU小助手 发布时间:2021-12-3 17:00
板子使用的是25M无源晶振,下文将介绍STM32F207的时钟系统如何将25M晶振时钟转换为120M系统主频时钟的。
) p" H$ d+ D+ H% X& B0 T' d5 a
0 [8 U7 m& |5 g0 ?; e01、时钟系统介绍
; K8 h  j5 k/ k6 v, X2 P; C4 E' @: U- w0 }% A  Z& g1 n
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
' ~; T& M$ F% R( a: z
                                                                    ▲时钟系统专业名词缩写
9 M5 v% h  L8 J* v- P6 o- l! g3 Q9 P0 P+ w
时钟系统关键组成部分9 y4 p7 A! j1 A/ r! ]

0 g. q/ C2 R: D; U- u: I: L01 内部高速时钟(HSI)
; S2 o( L. C) l- z* w' E
5 k* r2 S4 m2 l3 r; hHSI时钟信号可以通过内部16MHZ的RC振荡器产生,可以直接用于系统时钟或者用于PLL输入。- R9 Y; y4 q1 c9 l

( V& Q! b$ b  u, p6 g; yHSI的RC振荡器的优势是:在最小成本(没有外部器件)情况下提供一个时钟源。它的启动速度要比HSE晶体振荡器更快,但是即使校准频率后,它的精度仍然小于外部晶体振荡器或陶瓷谐振器。+ A( t/ g2 \' ~5 O' ]; ]/ Q
1 h: B( N5 F! D$ m5 }5 g
02 外部高速时钟(HSE)
* e# e2 c8 u; [5 ]" s! b) Y0 O
9 p) R! |7 A9 L/ y! B" k外部高速时钟信息(HSE)可以通过两个时钟源产生:  I( {# `# w) v1 e, {: A

$ K6 b& G& h3 b9 I0 n/ V① 外部晶体/陶瓷谐振器
( o8 B, o- `! Y7 W: U7 N5 `% h, Z$ t
$ r; }% }7 [8 i- K6 w② 外部用户时钟
+ @. ]* I# @. B5 a/ F0 |' p, U4 F6 c. J, F  N- o
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
- ]6 U/ [, B9 d2 U7 s
8 ~. _4 ]' t8 H& t7 d+ W
▲两种时钟源接入示意图
% I0 j8 M5 f" t
' ?& \. G6 l& [4 \4 Q5 o
3 v- Y. P2 l/ Q! }" ~3 ?5 ]+ z  N03 主锁相环时钟(PLL); z2 L) w) i+ X

9 I8 A. A9 C  d8 bSTM32F2xx具有两个PLL
& n0 Z8 ]; H  [4 ]' q" R9 ]0 |0 v$ o
① 主要的PLL通过HSE或HSI提供时钟,并且有两个输出时钟;/ ^$ @, Z. Q- Q' r  E$ b
3 s& x" W9 a) K- D% P
② 专用的PLL(PLLI2S)被用于产生一个精确的时钟去实现高质量音频效果在I2S接口;
8 \# Y3 M! s' L& }! C9 T/ C' G& e6 |7 f. _: ^
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
' y6 @6 |) Z8 J0 o0 K' v

* e# ?7 K9 o7 S0 e) [8 _7 o
3 v8 Z/ N- P/ THSE/M*N/P得到PLL时钟: ^# A( J3 R0 N% b  O, y& [
) h% `' Q6 |( Q% r/ [1 M$ H( d3 }" J
关于PLL锁相环说明
% H, N$ t, i! Z
3 ]. R+ s1 p1 O7 i& D
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

/ D2 H' T0 n$ Q2 n1 o7 u. A: S7 B" o
* M2 |: t# }. p3 L
从1处输入,3处输出是1的N倍。
9 K+ o, l; x. ^/ g7 q7 S* f; u0 Z+ n% W( j8 q8 }. a: {( A& L( I* c
3处除以N又作为输入,当1和2的频率一样,就锁定了。(之所以图上是xN,因为从2看向3的)4 M8 Z' m2 p6 e8 t

! A. [6 J/ i3 {! T/ _9 l8 g6 X- ]; O8 @# ?2 ?1 V1 U) ?

8 E( i  s5 @2 q4 P; C04 低速外部时钟(LSE)
; U: q! c6 P% ~# @( `* H" }9 Y$ N& b3 A; c" Z& G3 D1 z
LSE是一个32.768KHZ低速外部晶振或陶瓷谐振器。3 ]6 U. Y# e: D3 t6 M- h
: h' A1 z1 H* y7 `# [6 l. v) k
它的优点:提供低速但是高精度时钟给RTC外设,为时钟/日历或其他时间应用。
( P  |5 ^& ^4 [, s! V- D' u
0 l  J# h% _8 Q
* p) N7 _* ?2 C, h4 I" z( X: f+ ~9 `05低速内部时钟(LSI)' P/ p7 i) n& \" u4 \5 u

% u- j: E/ C# b" i; DLSI RC作为一个低速时钟源,它可以运行在停止和待机模式中给独立看门狗(IWDG)和自动唤醒(AWU)。它的时钟频率在32MHZ左右。
. Y) T2 G. R2 T3 ]2 D3 g. S  m! w5 f
02、代码分析! w& l/ I8 m, X) l$ z) p( h# d
时钟初始化代码在system_stm32f2xx.c文件中,大部分时候我们不需要修改时钟代码的,各个总线的频率我们可以在文件头看到。; d8 e2 h' [2 L+ u% ^: f7 W1 _5 z

! J" N; U* r$ P
  1. =============================================================================) X5 |) W/ c. B" H
  2.   *=============================================================================8 Z8 |& c6 V$ T
  3.   *        Supported STM32F2xx device revision    | Rev B and Y
    ' w  _4 p8 D( b4 ?
  4.   *-----------------------------------------------------------------------------; R3 ^/ y% t1 M# g; Q
  5.   *        System Clock source                    | PLL (HSE)7 H- D8 s( Q1 h6 R! V4 e& A
  6.   *-----------------------------------------------------------------------------  A- h0 v9 X) V) X. {$ Z2 e
  7.   *        SYSCLK(Hz)                             | 120000000
    * K* u2 s( K1 t# ?
  8.   *-----------------------------------------------------------------------------
    ( b6 i, W7 J7 K% x2 Q5 f" r
  9.   *        HCLK(Hz)                               | 120000000
    3 l7 E2 M/ {% T) O9 }0 T
  10.   *-----------------------------------------------------------------------------
    7 I4 i! k' |  Z! S( k# P2 q
  11.   *        AHB Prescaler                          | 1
    7 D( l0 l5 y( b& R
  12.   *-----------------------------------------------------------------------------
    * ^& m0 G" @! H- ^. D
  13.   *        APB1 Prescaler                         | 4
    4 S& p! ^$ q, e) J: L- y  v6 o" Z1 a
  14.   *-----------------------------------------------------------------------------
    / Q7 r( ?$ o# u& Y" `/ E: ~! w
  15.   *        APB2 Prescaler                         | 2
      G) o% l$ T. V& k. S  d
  16.   *-----------------------------------------------------------------------------
    + [- z+ t9 y) v
  17.   *        HSE Frequency(Hz)                      | 25000000
      g$ k: s5 Z9 Z8 S5 W0 O
  18.   *-----------------------------------------------------------------------------
      n. D2 e' A2 @5 y9 ?* l
  19.   *        PLL_M                                  | 253 q' L- {4 c# C$ K% I) S
  20.   *-----------------------------------------------------------------------------' N; b8 v6 R; S5 E" K
  21.   *        PLL_N                                  | 2400 V% P8 x2 E( D4 b  k- _
  22.   *-----------------------------------------------------------------------------
    ! R8 }# m) `+ U4 B
  23.   *        PLL_P                                  | 2! F" ^; _2 E- _
  24.   *-----------------------------------------------------------------------------( w, x) g( V% n* B1 M
  25.   *        PLL_Q                                  | 5! Q0 J% J9 }0 m' C- t
  26.   *-----------------------------------------------------------------------------
    5 g- g6 G8 Y' `2 a5 [- m& z- P- ^
  27.   *        PLLI2S_N                               | NA0 a5 e* K% |0 c% C9 D$ j
  28.   *-----------------------------------------------------------------------------
    0 s% [1 q- p6 h
  29.   *        PLLI2S_R                               | NA4 P/ m  f+ W1 T6 l4 `
  30.   *-----------------------------------------------------------------------------$ M1 z' b9 t( v' ]6 c) n" _- v* n  _
  31.   *        I2S input clock                        | NA
    ' U" ^) M  g" Q/ _- ]: O) J) f
  32.   *-----------------------------------------------------------------------------) d. X1 b% ~5 A" C/ t
  33.   *        VDD(V)                                 | 3.3
    3 s2 g. M. T7 L4 ^9 @
  34.   *-----------------------------------------------------------------------------  N' @* E2 a" x( C. b
  35.   *        Flash Latency(WS)                      | 3
    5 l% P5 i# P. h6 D: _
  36.   *-----------------------------------------------------------------------------5 |# e: Z- A4 ]/ d% p% H0 V& M
  37.   *        Prefetch Buffer                        | ON4 m  ^! w9 v; H) m! h8 S
  38.   *-----------------------------------------------------------------------------$ u- n/ D; K$ Y" O' g6 j
  39.   *        Instruction cache                      | ON  u7 k$ _4 r- M
  40.   *-----------------------------------------------------------------------------2 F* s* _0 Q" k# Y
  41.   *        Data cache                             | ON
    . z# `, C6 \" o9 H
  42.   *-----------------------------------------------------------------------------; |7 T# g4 _- O: Q# R. E
  43.   *        Require 48MHz for USB OTG FS,          | Enabled
    0 V# \% t) U' @5 e6 u% t
  44.   *        SDIO and RNG clock                     |
    , ?; T& s. a0 z4 D
  45.   *-----------------------------------------------------------------------------
    ' i3 \' K" _* p* j4 Q) A
  46.   *=============================================================================
    + ?$ e- f2 b. g6 x6 L
  47.   ******************************************************************************
复制代码
在文件开始定义的有系统时钟频率的全局变量SystemCoreClock,其他地方需要时钟频率,可以直接使用该变量。2 j7 C) p* g2 v( _7 K; b1 H* q" a
  1. uint32_t SystemCoreClock = 120000000;
复制代码
% Y1 C/ l) I/ L" \! Z
时钟配置从SystemInit函数执行,调用SystemInit的在汇编文件中startup_stm32f2xx.s(Keil编译环境)。1 ]7 i( Z: {' H7 i

5 x- E% n( N% C0 e
  1. IMPORT  __main
    , p4 T3 w0 v0 k% T) ^+ O
  2.     LDR     R0, =SystemInit  t" h2 B* G4 j1 u
  3.     BLX     R00 G3 v; ^5 L& Y
  4.     LDR     R0, =__main8 X* I  r+ Z- m# Y8 A
  5.     BX      R0' p4 G! j/ ~* A! v
  6.     ENDP
复制代码
3 Y6 Q8 g6 q0 b3 C
在这里说明一下文档版本的问题:. j1 I2 W, B$ m# W  t0 o; Q- |

& \! R- Z8 H: N" i# Z1 ^
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

0 S, }  f6 o6 j1 M' F; U* w+ c/ c* u. J4 A0 ]3 Z
▲STM32F20X_User_manual的V7版和V8版对比图- O  I: r5 o3 {/ r5 I% S0 z3 I' Q1 L
  C3 N0 i5 h1 o3 |
上述两图的区别是系统最大时钟从120MHZ变成了168MHZ,我的理解是同样是STM32F20X,ST由于技术进步或其他,使得新版STM32F207芯片超频支持168MHZ。
( q. t4 b: U1 V2 K
7 o- W* q' ?) D5 E. }8 o& V下面我们主要分析SystemCoreClock的120M时钟怎么从一个外部25MHZ的HSE得到的。' N% G" y7 g9 F- x$ a! S0 D7 K
1 `7 [# g2 f. B
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
: z# I$ O% |9 d  e; L

( }/ {6 x+ ~1 ]& M* I2 Q. ~4 G5 a$ U" ^! E7 t我们要从25MHZ的外部时钟得到120M的系统时钟,需要上图中标注的重要4点:
5 w: ?8 _1 u9 L* k4 u
1 Y$ J" b% v; Z* v* m- s1、使能HSE1 w3 A9 M! Q# c$ L- R/ c8 r* V2 y
$ z: C0 h# H, {
2、选择HSE作为主PLL的输入时钟( x$ J9 j" W7 n7 \" W+ \: x: ^

4 d1 v3 W5 Z# N) c  E3、主PLL倍频后得到120MHZ时钟
! i3 F( l( u" |$ F9 u
" f3 z5 r* v& `4、系统时钟选择主PLL时钟输出作为系统时钟
3 d' ~( w; o( m2 O3 G& c3 |% n' m6 ~0 @
我们找到对应的代码
; D2 b- \$ H9 v! ^- B. D& e- L' @$ D0 i, C: f
  1、使能HSE
! y) {1 K1 N' K8 K- g
  1. /* Enable HSE */
    # d% _+ d( U  \* j% x! j, ?
  2. RCC->CR |= ((uint32_t)RCC_CR_HSEON);
复制代码

' o9 z; @$ ~3 F& ^6 u在RCC_CR寄存器(RCCclock control register RCC时钟控制器)中,有打开HSE的控制位
$ H- a9 v' t" T) Z8 I
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
  b' D/ u5 x% i( c
9 \8 [3 R6 a" ], v% \/ X, K
2、选择HSE作为主PLL的输入时钟& Q( S& [$ ]0 M
  1. /* Configure the main PLL */. K/ t! C. z( |+ d) `) L2 i
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
    / W( j. Z9 V$ \( s% Y  S' H! H$ A
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码
5 `% ?; b8 D5 q! ^1 b5 N
RCC_PLLCFGR_PLLSRC_HSE就是配置HSE作为主PLL的输入时钟9 c% U8 i8 A% c) U& o

1 i4 h& V0 ~9 w+ ?: K  3、主PLL倍频后得到120MHZ时钟
* i! V  |6 d* Y; _
  1. /* Configure the main PLL */) I1 k. t0 P0 W8 Q- I
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
    - L, A: {, j1 G7 |/ A
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码

+ O% o6 \2 e! _6 R, Z4、配置主PLL作为系统时钟的输入时钟6 M; Q5 f% n' f
  1. /* Select the main PLL as system clock source */# q% T; J7 k6 q* B
  2. RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));; K7 p  @: c/ s3 J1 t7 b7 |3 a
  3. RCC->CFGR |= RCC_CFGR_SW_PL
复制代码

* y' }( O& X$ g$ A4 a' J对于主PLL的配置寄存器,在RCC_PLLCFGR寄存器中有说明
  D; W4 j* S/ [: n5 y8 ?9 a
, f- d" A& h6 k
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
4 K/ J) l" f; l6 k. G* t, B0 K
& _8 u8 a8 q$ M% b
整理后得知f(out)=f(in)* N / M / P3 R) z" h: G9 Y, C* I! u- W
  1. /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
    ! k, X: U6 O" F1 \% g. K
  2. #define PLL_M      25
    0 C) U/ B0 }6 |- Y" j' N
  3. #define PLL_N      240
    2 m8 r/ k$ S* y5 ^" ?
  4. /* SYSCLK = PLL_VCO / PLL_P */( A) K& i4 J" [1 H# Z
  5. #define PLL_P      2
复制代码

% p. s+ S. M, m, {; W这样就获得了120M时钟+ t& O+ k  c: d9 C! D
$ U) Y" ~: u! r* K
注意:' C4 H6 C( H) R2 n+ E5 \/ p9 n% _

' C$ d, ?! F, m9 e: S, @
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

7 B$ P8 u7 ^& B5 @( n& g
+ i& I# a8 X+ f2 r- J/ ~PLL_M大于等于2且小于等于63
3 e; V8 d( ~2 S; _/ }9 w" t4 M$ ?4 Z
% w' d* e4 J) f
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
+ W$ }, _0 L$ G, Y7 V3 Q
! H% T& z) F" f* E0 p
PLL_N大于等于64且小于等于4322 w; b( t  U& B' U
) G2 O4 j6 }- D( o
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
& d1 x. }% G' k% |: q2 r. o6 \9 V
; l' Z; i, ~, ^
PLL_P只能是2、4、6、或8) K; x' q+ c! i" k. O! _0 {

8 r- G- x7 [9 g+ J. Q但2对应0,4对应1,6对应2,8对应3。
. r$ m& p, f6 D7 ^. y4 q5 r. M, i) f- i, n, c
ST并没有使用if或case语句判断,因为对应的数据除以2减去1就是寄存器这两位的值,所以可以按照下面这样写,这种写法值得我们学习。+ s  T3 ?! G. P6 }; S* [4 a

9 v) X$ O1 [; k0 b. M(((PLL_P >> 1) -1) << 16)
: U, m& L% F( A) l, G, E0 G其他外设的时钟配置时. K* u. G7 C5 u4 p' w8 ]
  1. /* HCLK = SYSCLK / 1*/
    - Y7 o  A7 X8 z- h
  2. RCC->CFGR |= RCC_CFGR_HPRE_DIV1;( d  n* h2 l5 M- n$ d
  3. /* PCLK2 = HCLK / 2*/
    . f/ q* T+ |; f! U
  4. RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
    ( A/ q; _4 R; [. G  e! |' S
  5. /* PCLK1 = HCLK / 4*/. D% B: u. o$ x8 @
  6. RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
复制代码

' C" K2 x; q( z7 q" R03、备 注
- b' ^$ j% I) p0 _* d: x) S+ M
时钟中断
2 s2 V/ i7 C3 \! y! Y4 n! l" J
! d! {! B- N# ]6 K0 P# z( D
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

+ ~  W" s; F, i
) f/ j$ c6 ]- [. A( I可以配置外部晶振出错时的中断,还有RCC中断,因此我们可以在外部时钟出问题时,切换为内部时钟,不至于整个系统挂掉。具体见ST给的官方代码。
3 d- d! i, D; a$ t
" ~: ]7 H2 ]8 k1 K! Q 无源晶振不起振  |7 G: N& I1 H) L1 r6 P& M

: v  J, y  B/ e% y: @/ ?没有程序,无源晶振是不起振的,需要配置RCC时钟控制寄存器的HSEON位打开或关闭HSE振荡器。具体可以看之前的文章《晶振原理解析》。5 c# v; c/ L4 c9 T# f
7 ?' A% b, Q2 V5 T# \
关于APB和PCLK1 U+ ^7 X6 ?8 {& `; B  t; ?! c" o
( Y- o- o) B3 V0 [9 I6 D% R
F207是时钟图没有显示PCLK1和PCLK2,应该就是APB1和APB2  ~+ d5 S! `& r+ @9 H( Y

1 X+ ]% v7 W- A, g! z1 E应该指的是一个PCLK应该是PeripheralClock的简称,看F105手册* v. O' c; i9 c5 j! D; v* Q3 j

  L$ N( |" K$ D0 c9 g( H0 R# _1 c
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.jpg
1 ^3 M- `8 I# ]1 [6 x. }, ~2 P

" I# b& ~7 v- I+ }
4 O$ U. l5 E4 b. N$ E4 k' g# L' d4 ~- P* {, G3 R: B, u

7 Q$ q0 H( k* a/ W' y$ {4 J6 ?0 j& q8 w
5 r' k$ H1 i2 w6 l* u! K/ m2 l1 ^* n  K( Q& |
, u  i2 |+ H# I- g
收藏 评论0 发布时间:2021-12-3 17:00

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版