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

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

[复制链接]
STMCU小助手 发布时间:2021-12-3 17:00
板子使用的是25M无源晶振,下文将介绍STM32F207的时钟系统如何将25M晶振时钟转换为120M系统主频时钟的。$ P. ~2 T" u5 r( z1 d, A, _  g# x

4 M8 V8 I9 b( g; @; Y01、时钟系统介绍# h9 B& p, j0 w: m) n

; v: D4 r3 N3 O) W
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
! H8 E& u( R& E
                                                                    ▲时钟系统专业名词缩写  c9 N. Z* d6 @
2 I; y6 S9 O8 `
时钟系统关键组成部分  Q8 L# c! {" b4 a' S0 s
  ?4 M- r& a4 t3 P
01 内部高速时钟(HSI)5 B! k6 y1 t4 r- v

  X& p' K7 o- N4 nHSI时钟信号可以通过内部16MHZ的RC振荡器产生,可以直接用于系统时钟或者用于PLL输入。
$ A6 s! B8 n  b, g5 T1 @
3 a1 h5 b: u7 UHSI的RC振荡器的优势是:在最小成本(没有外部器件)情况下提供一个时钟源。它的启动速度要比HSE晶体振荡器更快,但是即使校准频率后,它的精度仍然小于外部晶体振荡器或陶瓷谐振器。
  t5 Q) B0 O+ c; ?  }( W; s
* J- ~; w- Y  }" g& D: y02 外部高速时钟(HSE)+ v5 c; r$ q" Y
! c3 k4 g# Y6 O: C" f6 M  e: i
外部高速时钟信息(HSE)可以通过两个时钟源产生:
( @, n: z) }: {' v/ h7 x1 J
4 q& N' v! M- t① 外部晶体/陶瓷谐振器
2 z2 ]- w; K' j4 S: x6 n! ~. L$ G. U2 g# B; W( u/ r) T
② 外部用户时钟
/ U) ?3 C7 A6 Q8 s0 f8 f7 J2 @' l9 Y: ~: n' k3 m
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
9 Y; J6 T& N5 g( d) g8 d7 p( m
  u  ~5 P! W& w' E& K
▲两种时钟源接入示意图4 e2 H. z3 u" E' C0 {" i# }3 P
5 O. L- l* ]- ^, H) @( G

' A1 S! C' n7 ?" `! L& H03 主锁相环时钟(PLL)
  A* `& i7 ~0 m/ T0 T+ {1 @4 g1 J( C; i/ u' R8 g! f" Z
STM32F2xx具有两个PLL. B0 p: Z# Z; ?: O  S5 j/ H( t9 M

$ G& ~6 S$ e' C$ ~① 主要的PLL通过HSE或HSI提供时钟,并且有两个输出时钟;
* b1 |, |9 \0 z5 L1 \4 f
) b$ G$ \+ J& ^/ t! |② 专用的PLL(PLLI2S)被用于产生一个精确的时钟去实现高质量音频效果在I2S接口;
9 _6 h4 L5 Q; \8 G  C2 F+ b, e& Y3 y6 o9 }
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

+ P, T/ I( r9 _. x7 g2 g
6 {* F5 H' g; m" W* e4 `3 D% N! k+ h$ K* S# `, R0 u8 |  b3 ~; q
HSE/M*N/P得到PLL时钟
2 }+ L6 o7 n" C6 p
5 U/ @) p* h$ |9 m; @关于PLL锁相环说明8 d; H' X9 X" |+ ~3 h/ ^6 `
7 ?3 [; C5 n9 h/ `! g& p
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

6 o- r+ e! M) x0 ~
0 b( s" z5 f+ p! E/ s, ?2 h) k3 N% R9 n/ G: ?% }
从1处输入,3处输出是1的N倍。8 @+ V: l9 d/ [1 J0 c

; `5 e8 l+ i, A6 n* ^4 I3处除以N又作为输入,当1和2的频率一样,就锁定了。(之所以图上是xN,因为从2看向3的)
; Z- x8 X7 ?) g. ]* M: ?4 r8 n5 f  m8 C1 M# {) D

' s, W" G& \8 f* b0 ~- j$ T4 @' v0 e, |0 |2 }
04 低速外部时钟(LSE)
) H7 d. }7 }% Z) K; a% {
$ }- J& U# u$ W+ n% Y; M1 qLSE是一个32.768KHZ低速外部晶振或陶瓷谐振器。2 V5 j! ?4 p0 }5 x9 Y  ]

  U2 i  t1 f* D3 n, P它的优点:提供低速但是高精度时钟给RTC外设,为时钟/日历或其他时间应用。
% o: B; a2 r1 x+ g0 t5 m" v8 G  B2 P2 I- Z( V

2 V# i) b) C9 O3 k9 \/ b3 N05低速内部时钟(LSI)
3 i5 Q2 T/ j/ E* n9 s) I: \: P0 c) R
LSI RC作为一个低速时钟源,它可以运行在停止和待机模式中给独立看门狗(IWDG)和自动唤醒(AWU)。它的时钟频率在32MHZ左右。# A+ e  |& Y+ j: h. g1 ~

, ~+ h0 m6 a/ ^4 K" x/ c$ g02、代码分析
, H0 g% m6 `, M1 i: P7 e$ a1 H时钟初始化代码在system_stm32f2xx.c文件中,大部分时候我们不需要修改时钟代码的,各个总线的频率我们可以在文件头看到。
8 M) N# K- h3 _, P) z! P
- Y: ~: [$ N8 d0 u; V+ R
  1. =============================================================================* \6 v4 |$ P  }* m
  2.   *=============================================================================
    " h6 k2 g9 t! N; z
  3.   *        Supported STM32F2xx device revision    | Rev B and Y+ I1 M2 Z. k, Z$ M+ j* F$ M3 e
  4.   *-----------------------------------------------------------------------------+ z$ I6 G. k" ~9 g; ]
  5.   *        System Clock source                    | PLL (HSE). O8 t- Y1 P8 _5 ^' ?
  6.   *-----------------------------------------------------------------------------
    ; }; i* m5 S6 R% j7 n6 V
  7.   *        SYSCLK(Hz)                             | 120000000% w) S' e2 [3 |* U7 X& d8 n
  8.   *-----------------------------------------------------------------------------
    ; ?" b- H3 M9 X# m! J' X, I+ @
  9.   *        HCLK(Hz)                               | 1200000004 k& Y/ @" j. ~  C1 Z
  10.   *-----------------------------------------------------------------------------# Y; G: h( i+ Q* L
  11.   *        AHB Prescaler                          | 1
    : n! d* h$ l3 G, O
  12.   *------------------------------------------------------------------------------ d4 h2 p6 s7 l% Y- P" x, \
  13.   *        APB1 Prescaler                         | 4
    1 c4 s9 d4 m/ Y7 I& P* W. U
  14.   *-----------------------------------------------------------------------------  _" [  a( p7 T% \% Y+ W
  15.   *        APB2 Prescaler                         | 25 ?$ @( j. a7 e8 d6 n8 W
  16.   *-----------------------------------------------------------------------------
    4 P, w8 _- H; ^0 Q' v+ |) ^
  17.   *        HSE Frequency(Hz)                      | 25000000* v2 Y/ v! m  T" ?. o
  18.   *-----------------------------------------------------------------------------8 B- P- T( y. H8 B4 _( T
  19.   *        PLL_M                                  | 25% P: M9 p3 j" Z  q
  20.   *-----------------------------------------------------------------------------
      B; J% L  d8 ~/ g
  21.   *        PLL_N                                  | 240
    % l0 B9 b9 J. _8 {1 m4 e  v6 W
  22.   *-----------------------------------------------------------------------------2 a9 @( N/ _% w0 c
  23.   *        PLL_P                                  | 2
    ! @0 T8 y# v; y; c6 ^
  24.   *-----------------------------------------------------------------------------; Q& ]% ^! ^% F; W6 y6 Z" ]+ W
  25.   *        PLL_Q                                  | 5; }. z: @' @5 u7 c. K# }
  26.   *-----------------------------------------------------------------------------
    9 Q- s% H+ |5 A8 Z8 f
  27.   *        PLLI2S_N                               | NA3 i1 s2 [/ b; F+ s% r/ L
  28.   *-----------------------------------------------------------------------------
    ) a7 Q: {& G, b( B7 K; h2 @
  29.   *        PLLI2S_R                               | NA
    7 {, ?- ?* v! Z, ?
  30.   *-----------------------------------------------------------------------------
      {+ o1 F7 D5 G
  31.   *        I2S input clock                        | NA- I+ n& M3 X. y: p- D5 a
  32.   *-----------------------------------------------------------------------------* B+ W/ |4 O/ T1 r8 u8 U! [( @
  33.   *        VDD(V)                                 | 3.3& g* d9 B. y+ Q5 r7 ^4 {6 \
  34.   *-----------------------------------------------------------------------------9 q# P- o' \2 A; H8 @
  35.   *        Flash Latency(WS)                      | 3
    4 r! o' m/ r* Y- K' E4 I9 \
  36.   *-----------------------------------------------------------------------------& }  |" t1 `2 T% L
  37.   *        Prefetch Buffer                        | ON7 T* T  W6 i( b$ D! _% J
  38.   *-----------------------------------------------------------------------------+ y8 N. w1 n9 K3 [* ~3 r( D
  39.   *        Instruction cache                      | ON* ]% L% I* Z8 w
  40.   *------------------------------------------------------------------------------ U: W7 y! T0 l. I2 {8 Y# ^
  41.   *        Data cache                             | ON
    ! C  |$ v; ]/ I& j
  42.   *-----------------------------------------------------------------------------8 v" N6 x8 J9 p: |. S) d& j" f
  43.   *        Require 48MHz for USB OTG FS,          | Enabled1 y! D- |7 a% {8 ]* Q5 p* C
  44.   *        SDIO and RNG clock                     |0 k+ x' t. d$ e( e  n/ v& x
  45.   *-----------------------------------------------------------------------------
    $ S, K1 M& _2 Z9 S
  46.   *=============================================================================' c5 }9 t/ C: o( |
  47.   ******************************************************************************
复制代码
在文件开始定义的有系统时钟频率的全局变量SystemCoreClock,其他地方需要时钟频率,可以直接使用该变量。
8 e8 x& q8 b7 w  T3 C  k
  1. uint32_t SystemCoreClock = 120000000;
复制代码

. Q9 m7 S: B9 r% x8 L" d6 y时钟配置从SystemInit函数执行,调用SystemInit的在汇编文件中startup_stm32f2xx.s(Keil编译环境)。
2 s. W' l% p1 |% P( I2 [9 _: `( k, ]" _" I' Y% P
  1. IMPORT  __main% S( p) ]9 x* h3 z2 E( W% Y1 x% b
  2.     LDR     R0, =SystemInit( a& h% ?* w, G0 a3 I+ s, _4 `  }2 v
  3.     BLX     R0
    ! m. j9 F2 p$ A  M
  4.     LDR     R0, =__main* n6 R9 K* _+ k# O3 C
  5.     BX      R0
    ; D" P* n. R- Q8 b$ x
  6.     ENDP
复制代码
: i- C- s6 R, t0 a
在这里说明一下文档版本的问题:
1 j' p, @6 \9 J0 Z6 q& E' p, ^* A
. [. j2 Q% U3 ~! [
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

& n1 D( K+ u/ h' U
$ n7 h" [1 W6 T$ i2 k& ]% i" Z▲STM32F20X_User_manual的V7版和V8版对比图0 E, E; E( \% l* p
0 O% R0 D' V0 P2 m, R  X* J7 ]
上述两图的区别是系统最大时钟从120MHZ变成了168MHZ,我的理解是同样是STM32F20X,ST由于技术进步或其他,使得新版STM32F207芯片超频支持168MHZ。+ A7 l# X2 s! @4 q$ v+ w( k  b
$ b  k" p- K7 k7 Q2 `* x; y
下面我们主要分析SystemCoreClock的120M时钟怎么从一个外部25MHZ的HSE得到的。
- n' U/ ?, f/ N
* p* i, ?0 u# I' K% B; A: g
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

+ a0 `7 ]# @- I  A
5 Q& M& B+ g; N  o% F; y4 H* r我们要从25MHZ的外部时钟得到120M的系统时钟,需要上图中标注的重要4点:
$ [2 C2 j; m* h. D, N9 C: a7 t& ^6 d3 `$ r, x" Q. |
1、使能HSE
7 Y) M3 r7 ~3 ]
1 ^8 \* I# y- H: R2、选择HSE作为主PLL的输入时钟5 o3 K- i0 [0 Y8 S

6 H- |' u8 j4 b6 q+ e/ h( x3、主PLL倍频后得到120MHZ时钟
- C- C) k. g  _  R3 S1 A& w/ V5 u: O
4、系统时钟选择主PLL时钟输出作为系统时钟. [  Q$ H  \, l5 ?  i, w

+ T; e( ~& `/ q7 `我们找到对应的代码% H7 c  ~$ H6 v. E9 c

1 D9 v, I/ X+ _2 G  1、使能HSE7 p) g$ v4 A& ^: g. x) A9 [8 q
  1. /* Enable HSE */: U4 s& c" r* l2 F$ G/ i
  2. RCC->CR |= ((uint32_t)RCC_CR_HSEON);
复制代码
# W. O/ \& I0 U2 \
在RCC_CR寄存器(RCCclock control register RCC时钟控制器)中,有打开HSE的控制位& ^' V) z; j( S/ _" ~$ ^
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
  u" o9 U( I7 _; J  Y( {
/ k: j, m# y8 H7 K. P  Z/ `
2、选择HSE作为主PLL的输入时钟$ n; y# h! d9 M( C4 S( o
  1. /* Configure the main PLL */! S9 P, P4 W% O+ y
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
    " Z* B6 ~9 I/ y$ B9 h' Q2 t3 g0 n
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码

1 l% Z! @; ?/ Q. ]8 ]2 Q# r7 _RCC_PLLCFGR_PLLSRC_HSE就是配置HSE作为主PLL的输入时钟% `+ H4 h2 i$ L6 _, h' U& H
: D, W& W: B, F  D
  3、主PLL倍频后得到120MHZ时钟1 A7 w4 B" g4 I' ^* g
  1. /* Configure the main PLL */
    % N# h) h4 U9 |1 t
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |+ p6 p% e! V4 [8 e4 l4 ]7 E
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码
5 b6 R4 c' g' \" b6 U$ y+ Z
4、配置主PLL作为系统时钟的输入时钟2 b2 v! D2 y( s7 [  J& y- C
  1. /* Select the main PLL as system clock source */1 s! h; D0 s; ]
  2. RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    3 O% R/ p6 ^$ n  Y
  3. RCC->CFGR |= RCC_CFGR_SW_PL
复制代码

0 i7 u4 m* W0 ~# Q, ?对于主PLL的配置寄存器,在RCC_PLLCFGR寄存器中有说明% U$ d) \* \; H9 U  [# r0 e4 v$ \

9 |$ ?" ^1 D6 [: J" L
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

; G  c! f5 w1 A3 V) {! }) R: D' I+ q2 J3 x/ s
整理后得知f(out)=f(in)* N / M / P+ z& ~' {) I! \, W! R; m3 g
  1. /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
    ! |, Q* B: ^, J' h
  2. #define PLL_M      25
    + @$ |( O% U/ q' @/ a
  3. #define PLL_N      240
    % p" H- Q7 v0 B+ S4 [- s6 S
  4. /* SYSCLK = PLL_VCO / PLL_P */
    ! |3 ?( _6 a* L- e5 t8 Z
  5. #define PLL_P      2
复制代码

. Y# G2 u9 O( z2 I; \这样就获得了120M时钟' Q: d; @# P2 x- v9 L; `

' M* }. h4 j* I' h" ^8 Z注意:
- P% U& U+ }# B
  b7 `3 f$ c3 O9 m* X0 u
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
/ ~9 a6 V5 G) t8 ]8 k" T

/ W5 ?! h5 J& ?5 A6 p' IPLL_M大于等于2且小于等于63
- o* C& W( E! N3 R# M5 M
/ m- L; H( I: `. P7 Z5 W
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
* o$ P) Q  }2 s9 W4 p. d# ^" |

& y2 O+ s, K2 H9 n8 x0 bPLL_N大于等于64且小于等于432
2 k! {  t# F- v2 r" b& h% v
$ P6 e. Y; p; f2 G: [" e
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

1 e; R, N+ e" m. N5 H! \
% G! p% v5 `. ^! z& P! FPLL_P只能是2、4、6、或8
9 z# O) l: i% ~; H7 K* k: Q' S! O# ^$ s- Z4 Y# @& W
但2对应0,4对应1,6对应2,8对应3。3 [, W+ G; H/ f* @
5 ]7 i' L+ Y; n5 ~/ i' p
ST并没有使用if或case语句判断,因为对应的数据除以2减去1就是寄存器这两位的值,所以可以按照下面这样写,这种写法值得我们学习。
& M9 F) q& B- _' q2 e6 d1 O
  W% D& Y* ]* n2 q9 u5 S7 }( H(((PLL_P >> 1) -1) << 16)6 _2 k3 ~: u7 d% g* Q1 U6 H, U
其他外设的时钟配置时
( R, f5 D! z  {& K: h$ H" ?
  1. /* HCLK = SYSCLK / 1*/
    ; f- k' R  @; h2 O
  2. RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
    * c$ ^8 f6 b+ }$ P* E- g$ b
  3. /* PCLK2 = HCLK / 2*/  g; x6 B4 t2 \- f' F% a
  4. RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;2 y/ s7 k: }1 @8 z) k+ O0 B
  5. /* PCLK1 = HCLK / 4*/
    7 U( J$ u0 T, n% d% ^2 z" u
  6. RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
复制代码

. m) ]' i% Z$ y03、备 注
5 ^! Y$ @) C+ [& r2 w3 H
时钟中断0 A  T- k* J+ `. I7 j3 z1 c
0 r( O/ W8 \+ I2 d+ ^
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
8 ~4 p5 u3 o( s9 x! g  }
2 R- t  Z  c. J4 \' W- s
可以配置外部晶振出错时的中断,还有RCC中断,因此我们可以在外部时钟出问题时,切换为内部时钟,不至于整个系统挂掉。具体见ST给的官方代码。( K% p$ ~" S/ g, Q0 l' Z
5 }* m1 B7 I  Y" X
无源晶振不起振5 B+ z; K$ I8 _

1 f4 o: O" u3 H/ r* M没有程序,无源晶振是不起振的,需要配置RCC时钟控制寄存器的HSEON位打开或关闭HSE振荡器。具体可以看之前的文章《晶振原理解析》。" D  c' H! o7 R/ y- Z2 A) `

# |( @$ N) B9 b 关于APB和PCLK
/ K% @3 w* y; p2 s$ c$ D8 R8 B: t
7 K' `* d0 Y5 y9 L: }3 ~1 a
F207是时钟图没有显示PCLK1和PCLK2,应该就是APB1和APB2
3 p% E( g$ J2 h6 h2 f4 o0 N3 f* t# p0 `% ^3 m  C6 H, G# L
应该指的是一个PCLK应该是PeripheralClock的简称,看F105手册
7 }. Y( n6 @6 P9 t4 N* e
, U8 y( D9 I" C/ p
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.jpg

8 i7 q5 O" f8 c/ K9 m" |6 _6 z* f' C  W+ _* T

8 W1 G9 R  U3 U9 y
% t4 M- c0 X7 g" J( u0 N  S! `" ^$ [% o, }- c2 W
: O, J' i1 ]5 x7 ?( `! S
$ z' y) v" ^( {0 G, h2 P

& s# B. H2 }- i6 w; R4 [! S
收藏 评论0 发布时间:2021-12-3 17:00

举报

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