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

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

[复制链接]
STMCU小助手 发布时间:2021-12-3 17:00
板子使用的是25M无源晶振,下文将介绍STM32F207的时钟系统如何将25M晶振时钟转换为120M系统主频时钟的。
  E4 ?8 B& c3 g% S: b0 J
! c6 v# m- m) S# p01、时钟系统介绍! D% Z0 l  ^% f

8 Y, _$ `' F( d+ Y
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
' }3 |4 g( G( \1 \& Q
                                                                    ▲时钟系统专业名词缩写
) E: ]0 d6 h3 t( O9 ?3 X" H- @/ |) B1 G
时钟系统关键组成部分- V8 [; u0 V8 k7 \; o8 T

7 F: x# E: y  ^9 @& d2 E01 内部高速时钟(HSI)
/ q: H; C4 |$ B$ h9 k7 h. l
2 n/ b! n) X( R, G" VHSI时钟信号可以通过内部16MHZ的RC振荡器产生,可以直接用于系统时钟或者用于PLL输入。2 M/ l$ S6 L- C9 g! H0 K% X  G: N
" Z$ Q; i' {- w0 o
HSI的RC振荡器的优势是:在最小成本(没有外部器件)情况下提供一个时钟源。它的启动速度要比HSE晶体振荡器更快,但是即使校准频率后,它的精度仍然小于外部晶体振荡器或陶瓷谐振器。
& m1 F6 p# j8 t# O8 C8 F0 |4 f0 T4 I$ b2 j; s
02 外部高速时钟(HSE)
; d: D+ G2 R* G: a1 u, a6 f2 Y, l: v
# i6 ?- o: ~& ^. B. T外部高速时钟信息(HSE)可以通过两个时钟源产生:& \+ t4 N; t  q. o6 O
8 V$ k1 U+ Q- @8 W- d& C- x
① 外部晶体/陶瓷谐振器5 f: V$ v2 q1 M, t! u9 U

1 \8 F- g! J  `+ R! K" O② 外部用户时钟) O. C/ T0 \: \/ v$ Q6 \6 r

. f& V4 H' j7 E$ ^. Q0 f
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
( B+ U- Q" D% E# n# F  G/ ]; z

7 c5 b2 T; {  H0 f" z3 A▲两种时钟源接入示意图' k) N5 o0 H3 Q2 X0 F( ~! o0 Z

- _) O- e! b; J: x- T- W& S. `" p2 ?% \( a! |0 a1 K. B' z; q9 ]
03 主锁相环时钟(PLL), m& Z5 ^7 Q4 b* y! ~: P

6 |  h' n! l3 {" {# }; c  {STM32F2xx具有两个PLL
' I# v' S) \3 n  `4 y% {0 ~( S% ~. @% f8 P7 y: ^6 o3 \5 h7 s2 f
① 主要的PLL通过HSE或HSI提供时钟,并且有两个输出时钟;
5 l+ }4 c5 z* \  {8 \$ H1 |% o! D0 v! Z
② 专用的PLL(PLLI2S)被用于产生一个精确的时钟去实现高质量音频效果在I2S接口;
/ Y' \8 D3 p+ ^! j
4 i7 C3 f% v$ A! {, m
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

( J2 m' u( k" t( ~
, }, k' d6 }8 ~; E* k  I$ j) I8 w' U' ?7 O& i$ X" G1 Z
HSE/M*N/P得到PLL时钟
" i+ Z$ C! _9 l6 ^2 ?0 a% z* C
# ]5 |2 n1 W+ c关于PLL锁相环说明
( `' y9 v4 [* e& S7 u
1 J1 V" U  M/ ]( u
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

7 m2 I* G: ^' I3 M6 Q% y$ S
% j" P# `' W0 B# y/ R) ^  u: h; T! Y9 r1 M) y
从1处输入,3处输出是1的N倍。( M) ]4 ]* s: i+ n: ]
( o3 F. V" Z" y
3处除以N又作为输入,当1和2的频率一样,就锁定了。(之所以图上是xN,因为从2看向3的)
7 q+ U0 B, m6 L0 D, l& U( t2 @8 P3 \" c) {. B; H: K
8 e& \% h' d3 N# x7 t$ @* Q5 z
8 ~: F  p, T4 j  Z) X
04 低速外部时钟(LSE)
! A" L5 B  H! N2 a# _  w- V/ q) ?' h
+ }8 u# F8 N3 w' K* ]+ oLSE是一个32.768KHZ低速外部晶振或陶瓷谐振器。1 y/ p0 M& F  o5 a3 @
: l$ k6 T" D! Y+ \
它的优点:提供低速但是高精度时钟给RTC外设,为时钟/日历或其他时间应用。
7 L% D% x, Y' Z9 E
+ L  C8 H3 Z- f" l# H/ n) t1 r9 H9 {9 c) y% z
05低速内部时钟(LSI)  @8 h1 V) S8 c* t1 x
5 `4 W3 `. m' x: u. k3 R
LSI RC作为一个低速时钟源,它可以运行在停止和待机模式中给独立看门狗(IWDG)和自动唤醒(AWU)。它的时钟频率在32MHZ左右。
6 G* {6 V; }- D7 E& j5 }
9 X) L0 r. [3 Q, A0 o& t02、代码分析0 f3 ?, Y6 ?1 ~1 N7 O: c2 V+ {
时钟初始化代码在system_stm32f2xx.c文件中,大部分时候我们不需要修改时钟代码的,各个总线的频率我们可以在文件头看到。4 }1 W. Q) Z6 L

# P  B" Q' z2 ]! u7 w, B
  1. =============================================================================
    4 X$ m4 s( {& U  D  Y& H0 b
  2.   *=============================================================================
    ' C( ?2 B# @2 t. w. n! p, R
  3.   *        Supported STM32F2xx device revision    | Rev B and Y$ e8 L& v5 X$ k
  4.   *-----------------------------------------------------------------------------  G( |  T1 Z" c2 o
  5.   *        System Clock source                    | PLL (HSE)
    ! n7 _& w" c- c) e/ j. L3 {
  6.   *-----------------------------------------------------------------------------+ |. G4 e+ S- k6 B
  7.   *        SYSCLK(Hz)                             | 120000000
    * \  C8 p6 V5 ?
  8.   *-----------------------------------------------------------------------------8 f5 _' p7 s, b' N# v
  9.   *        HCLK(Hz)                               | 1200000003 Z/ a& w' T! N+ d1 t$ U
  10.   *-----------------------------------------------------------------------------
    ! X* P( p, [- b* c! y$ V
  11.   *        AHB Prescaler                          | 1
    2 C7 H5 s: p+ V- j' \' a. @
  12.   *-----------------------------------------------------------------------------# B2 ?: n6 d# Y, j5 ~
  13.   *        APB1 Prescaler                         | 4
    0 P$ ~7 v1 t5 P+ x2 J
  14.   *-----------------------------------------------------------------------------. V. x5 @8 k/ P, j7 S( z! A$ m2 l
  15.   *        APB2 Prescaler                         | 22 }4 X! k2 J6 m6 T: J6 x+ _8 j
  16.   *-----------------------------------------------------------------------------1 x# u8 g5 W( n+ m
  17.   *        HSE Frequency(Hz)                      | 25000000
    ' g) Q6 \5 z+ T. K: L% `% G
  18.   *-----------------------------------------------------------------------------
    + o( _+ J1 A/ N5 k# \: \0 `
  19.   *        PLL_M                                  | 255 Z$ M4 X1 y; t: T" @$ p( S6 S
  20.   *-----------------------------------------------------------------------------
    6 w& W. z( v% v6 S) g+ h
  21.   *        PLL_N                                  | 240
    / P# y2 u+ r9 X5 |
  22.   *-----------------------------------------------------------------------------. r3 y" o/ J) t( b' C( O2 C
  23.   *        PLL_P                                  | 2
    # e$ O- \& V+ D8 R: G# \% s0 ?* O
  24.   *-----------------------------------------------------------------------------$ S4 p" l1 f& i3 _& }
  25.   *        PLL_Q                                  | 5
    ; O# F! s- |( T; i7 [  z
  26.   *-----------------------------------------------------------------------------6 e4 V+ F" y  {  c
  27.   *        PLLI2S_N                               | NA
    ) p5 q  R+ J* g/ G9 R- c( @3 ^: B
  28.   *-----------------------------------------------------------------------------
    % O& k* }4 e& a! c+ K& q
  29.   *        PLLI2S_R                               | NA
    7 A) h: @+ q  r* u
  30.   *-----------------------------------------------------------------------------9 I* m- j8 z" U; U) N$ m
  31.   *        I2S input clock                        | NA
    2 _( {/ j; \$ n0 C# L( N
  32.   *-----------------------------------------------------------------------------
    ) O( U+ [# b# }. q7 p! W5 s7 `, v+ M
  33.   *        VDD(V)                                 | 3.3
    - c, F  F1 `8 l* V( t& ^- M4 Y) e
  34.   *-----------------------------------------------------------------------------8 k# K& l' v* w6 k9 Z% Z
  35.   *        Flash Latency(WS)                      | 3
    6 K% w9 V$ h6 \+ |3 d
  36.   *-----------------------------------------------------------------------------
    , f. y0 U% E) z4 J
  37.   *        Prefetch Buffer                        | ON
    5 w% R, F8 w+ g' T8 g$ I  E
  38.   *-----------------------------------------------------------------------------3 I, `8 ^2 C5 h; p. e! p. j
  39.   *        Instruction cache                      | ON  U: W" L8 ~  r
  40.   *-----------------------------------------------------------------------------
    . Z8 |3 S" }5 B5 h' J7 a
  41.   *        Data cache                             | ON# ^, D" R6 G  V
  42.   *-----------------------------------------------------------------------------3 b7 F7 p( |/ Z0 q4 O
  43.   *        Require 48MHz for USB OTG FS,          | Enabled
    4 A8 L" N' b/ G6 L9 m
  44.   *        SDIO and RNG clock                     |
    # D4 g% f0 n  e# f3 ~: e. q
  45.   *-----------------------------------------------------------------------------6 l/ T" Y. L! b# G8 j7 \6 k& U
  46.   *=============================================================================
    , L$ e' [2 o0 Q* a0 ^. t4 [  s0 j
  47.   ******************************************************************************
复制代码
在文件开始定义的有系统时钟频率的全局变量SystemCoreClock,其他地方需要时钟频率,可以直接使用该变量。
4 j7 r& u! Y& p, Q* N
  1. uint32_t SystemCoreClock = 120000000;
复制代码

1 ^8 y' h- r% p* R, e时钟配置从SystemInit函数执行,调用SystemInit的在汇编文件中startup_stm32f2xx.s(Keil编译环境)。
8 c6 ]- W1 S2 T& h
: f8 v0 D6 |$ ]
  1. IMPORT  __main5 W# v4 b' f. d8 g! F
  2.     LDR     R0, =SystemInit- R: q2 J6 I1 z! i# Z
  3.     BLX     R0) i" q8 t# q$ [: `
  4.     LDR     R0, =__main" z4 ?* v! M( I, z) l8 y3 b0 R
  5.     BX      R0- V0 E2 \& U9 I; g3 P6 ]. H& P
  6.     ENDP
复制代码
* d9 @6 c# t- o3 S
在这里说明一下文档版本的问题:
; S' [6 Y2 z' E' `* Q5 R
0 d. c* \/ B2 [# \/ W
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

  v2 ~! y; Q& {9 z" H- b" b- k9 a# H$ @7 U, {/ _
▲STM32F20X_User_manual的V7版和V8版对比图" w6 D0 H6 M  I7 [( A) Z# H
/ ~; f9 {4 n8 c9 V: Y* u
上述两图的区别是系统最大时钟从120MHZ变成了168MHZ,我的理解是同样是STM32F20X,ST由于技术进步或其他,使得新版STM32F207芯片超频支持168MHZ。0 t6 ~! k+ I! S1 P' m
% s# V7 w$ _$ r% Q; d
下面我们主要分析SystemCoreClock的120M时钟怎么从一个外部25MHZ的HSE得到的。8 }* l! N, I8 [

! y- e- T: b' B$ s
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
0 P9 W2 A. B! D& O# |

1 _: e- e' Y2 F( @( Z. o" Y* D, P我们要从25MHZ的外部时钟得到120M的系统时钟,需要上图中标注的重要4点:
3 x6 |" i/ r4 ~  S6 B( W+ F; `: |: h, K& |% f
1、使能HSE
* o: e; }) q. ?7 j$ ~' ^
* s, W# U$ q* N" d! C2、选择HSE作为主PLL的输入时钟
- x* Z6 G+ W+ L) K0 H' ^, O) `# K$ ?4 A
3、主PLL倍频后得到120MHZ时钟
1 R0 k; x& C$ {. O  {8 y
4 K$ o; Y, {: V3 O. p" y' N' f% F4、系统时钟选择主PLL时钟输出作为系统时钟' F0 j' Y4 V9 G% f$ C3 C
1 t7 `" v. y" e" ^% Q/ m3 V2 R9 J' H
我们找到对应的代码
: L8 g& s# M3 P4 N; M$ B" Y2 `- L. `7 F9 s# T2 J+ U: _
  1、使能HSE% T7 G) [  K2 c3 m+ K) i4 e
  1. /* Enable HSE */0 W+ ]' `1 n  n; q& |- t. n
  2. RCC->CR |= ((uint32_t)RCC_CR_HSEON);
复制代码
# ~- V) ?, {7 v9 G1 x% A. `: Q2 q
在RCC_CR寄存器(RCCclock control register RCC时钟控制器)中,有打开HSE的控制位% ~8 ]  B! n2 d
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

$ k3 m1 z5 _8 `3 n) _
3 u, v5 }$ z; i1 n2、选择HSE作为主PLL的输入时钟
0 [: h2 _5 }' e4 n9 O) j2 h
  1. /* Configure the main PLL */9 M  s9 N6 C9 n- J4 x: S, Z) |
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |4 Z- P' {% r6 W0 w* r5 Q  T- J/ F  b
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码
: V. b! h7 i0 I& @6 ^
RCC_PLLCFGR_PLLSRC_HSE就是配置HSE作为主PLL的输入时钟
. s# e  n0 v0 h* W( d; ~9 M
/ ?! j  Z3 L8 G, w9 Y# s  3、主PLL倍频后得到120MHZ时钟7 `6 A: v' }( J* J9 s  U. C
  1. /* Configure the main PLL */
    5 W* M3 k% k; A" O; m9 z
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |! q9 N" D1 Q& h' |8 z6 X) @
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码

8 H+ `! \9 P) [! b4、配置主PLL作为系统时钟的输入时钟& M1 t. o" |) f& l% R+ i( j( g' j
  1. /* Select the main PLL as system clock source */- ]4 t: R) ~. x# \! Q6 I. @
  2. RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));/ D# N2 f$ A: a4 W! ?
  3. RCC->CFGR |= RCC_CFGR_SW_PL
复制代码
( B+ l! b4 L  P; Y1 O
对于主PLL的配置寄存器,在RCC_PLLCFGR寄存器中有说明% _) T  }1 g7 u$ y
& v* x1 p0 Y# m" ^( m
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
( T' u. q: x2 D) k* I+ g. l0 g
$ ~# Q) G+ e! b( d; ^
整理后得知f(out)=f(in)* N / M / P
; s3 _) }1 ^2 i- w) i
  1. /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */- \5 L# J' s; f& t' b: o2 ^
  2. #define PLL_M      25. F: s8 H- L8 }2 E
  3. #define PLL_N      240
    & w3 ?7 p: {# O
  4. /* SYSCLK = PLL_VCO / PLL_P */
    & W' r; P  p1 m
  5. #define PLL_P      2
复制代码
% }0 v' g: s: P+ ~# c5 H
这样就获得了120M时钟
6 W" Z8 m6 \( t" N
) H# A6 L6 _+ l注意:
; V( c5 X6 z1 H# K% [% w
8 X( o' b. w* L' H7 N8 X8 u
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

$ n; O& {( `9 B/ Y' U$ i& ~2 D3 h$ k- x4 w$ ]* @1 e, _0 ^7 d& ^& p
PLL_M大于等于2且小于等于63$ L! ]5 e) a2 `7 F0 S' G6 o% o
& Y5 Q4 G2 f$ }1 w# r
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
3 R; J8 F% O6 F
7 t6 Q  M8 J  a& m) |8 T0 D1 r
PLL_N大于等于64且小于等于432
8 V( s+ L! [  U# R% |1 k2 X6 a
2 j. }2 q$ p) m- ]
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
% \3 |3 q8 _% U* Q/ M3 Z

. A4 g/ Y( C. w$ ^3 E* q8 ]9 {PLL_P只能是2、4、6、或83 \# p( {4 ?" M% K; I' O

; A+ r% F$ `) o* Y但2对应0,4对应1,6对应2,8对应3。, A9 m, P9 l6 b' F) B7 L7 m9 d% T" K
5 [1 c, W! y, w
ST并没有使用if或case语句判断,因为对应的数据除以2减去1就是寄存器这两位的值,所以可以按照下面这样写,这种写法值得我们学习。
" p" o. B/ `4 u7 u7 I- _% B0 u. C; ?& M
(((PLL_P >> 1) -1) << 16)5 U; g* V1 e' k, V1 S. F6 \
其他外设的时钟配置时
4 O9 M, ~; K  ~6 ?% l2 `" r5 i" G; r
  1. /* HCLK = SYSCLK / 1*/
    ! Z. g- o8 h$ A! G
  2. RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
    % s; Q% Y* q4 n+ `
  3. /* PCLK2 = HCLK / 2*/" h, o& K' ~9 z
  4. RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;' C/ P) `- g+ {8 Z7 S8 y; R/ a* D
  5. /* PCLK1 = HCLK / 4*/
    # W. I! h9 l/ N5 {5 b2 o
  6. RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
复制代码

/ k3 n9 l$ ^/ k: t; `03、备 注
+ T" g7 r1 T! [; w7 h
时钟中断. V2 P. N" W; k1 s! A2 u* x
& [9 O; r' V2 o# x  w
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
  L: P0 H9 \0 L* L. X
  m7 V. g  ]) F2 {3 n
可以配置外部晶振出错时的中断,还有RCC中断,因此我们可以在外部时钟出问题时,切换为内部时钟,不至于整个系统挂掉。具体见ST给的官方代码。. x; F6 r/ [: ^" h" X

1 M- O2 w: z5 _& D 无源晶振不起振; m! j* Y- ~: P6 E, v
( U3 w  q2 n8 P2 a
没有程序,无源晶振是不起振的,需要配置RCC时钟控制寄存器的HSEON位打开或关闭HSE振荡器。具体可以看之前的文章《晶振原理解析》。
/ {2 r% ~, C' m) o1 f. w- J( _
/ K3 ]7 w. Q$ q: e) U, V+ f 关于APB和PCLK6 y- q! l# D/ N) f

) F& a: @) b) O" wF207是时钟图没有显示PCLK1和PCLK2,应该就是APB1和APB2
4 F; [, v: |, [( r& f. j* C
) S" i6 }2 S5 H+ {应该指的是一个PCLK应该是PeripheralClock的简称,看F105手册* U3 P, u3 Q& M( g5 p

! P8 S3 y% K( N4 ~
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.jpg

5 H% F/ V* a  q& [/ J( _  @9 i: d( \! o+ e6 {
" V( g4 d) {9 }. x5 S
- S: b  z( x" K$ U, {) e

5 J7 e  G( j5 f  E8 }, S2 x# p; w& B) O
; X! V& |% S. c9 {  [0 D; s# G+ d, c9 `

& @6 S5 G/ N$ K: @% _  m$ X
收藏 评论0 发布时间:2021-12-3 17:00

举报

0个回答

所属标签

相似技术帖

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