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

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

[复制链接]
STMCU小助手 发布时间:2021-12-3 17:00
板子使用的是25M无源晶振,下文将介绍STM32F207的时钟系统如何将25M晶振时钟转换为120M系统主频时钟的。
5 L- b2 j7 C6 M! l' m1 T5 w
8 X3 v% ?- q1 ]) E$ w3 S0 G2 E$ ]" l01、时钟系统介绍
% C5 q0 b) E8 R$ t
8 p9 H( T/ \: o% c5 B8 ]- r1 @$ l
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
+ r; [% r" r4 h. h
                                                                    ▲时钟系统专业名词缩写. W4 g3 p$ b( w7 P

" v: b! f9 S% ]5 y时钟系统关键组成部分
$ U3 y" u4 i# j8 s$ q
% F/ U  ]- ]8 U7 ^$ I( z! L01 内部高速时钟(HSI)& m' b- x2 d' x& w: n7 }- c9 `

# F* P8 T9 C7 X9 [% a( F0 q' SHSI时钟信号可以通过内部16MHZ的RC振荡器产生,可以直接用于系统时钟或者用于PLL输入。
) m! Z( m4 C7 g0 [( m
* I0 P4 t4 u/ ~  [+ @/ p  h1 QHSI的RC振荡器的优势是:在最小成本(没有外部器件)情况下提供一个时钟源。它的启动速度要比HSE晶体振荡器更快,但是即使校准频率后,它的精度仍然小于外部晶体振荡器或陶瓷谐振器。- d# s8 [2 a/ ~0 U) X/ ^

/ [, a3 g: x  z4 N02 外部高速时钟(HSE)
9 e5 `5 P2 z6 z
) l3 B" r8 ?4 w3 p1 B外部高速时钟信息(HSE)可以通过两个时钟源产生:
! c9 H6 X! s0 ~' j9 v$ B
% x) |2 p9 y$ E① 外部晶体/陶瓷谐振器
0 F" o+ L, ?7 k' T# w, w. @
, J3 U& T9 |7 H4 W② 外部用户时钟5 g* |8 b0 e9 T+ H& a& p
5 C9 X! p1 H" f6 v' K: k, j
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

# e. J8 l: \& R8 k2 D
$ A& ~  l6 ?$ C6 T▲两种时钟源接入示意图
, p, V( i" T( @1 y) T) N/ R$ e/ d: F9 V" e( r: N

0 P9 }( l; G0 e03 主锁相环时钟(PLL)% V: a; H$ p6 Z; M9 U
1 j8 B2 R& x6 O. w1 @
STM32F2xx具有两个PLL3 Q2 C8 z* m' s( Y
/ x1 V9 q: @4 X2 Z! o
① 主要的PLL通过HSE或HSI提供时钟,并且有两个输出时钟;; K: l, Y3 V4 Y5 G# W& k
0 h! w7 p) p" c0 k9 l4 _; I
② 专用的PLL(PLLI2S)被用于产生一个精确的时钟去实现高质量音频效果在I2S接口;
- t9 c! B9 M. b9 ]  C. o8 Z/ z! m# Z
/ ?8 N3 j5 J0 {) V( X' j
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

  p4 _; O. b! B  t
1 f4 {6 B3 D: H! w; I# _1 Q" N4 J7 W/ H/ [2 w8 v5 y" ?9 j
HSE/M*N/P得到PLL时钟
+ E/ R; I0 m# u% t4 K! b& m0 s2 W9 e) |8 u$ ]
关于PLL锁相环说明
. Z9 K6 d1 D' L$ b( b2 i; B
7 Y! y7 I1 i7 a( @
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

/ V# }+ J3 Q1 J4 G4 F. l2 a3 K2 \
3 h1 g' z' I  E8 E" j, P* h- w: G1 h% V  q6 M, h5 j
从1处输入,3处输出是1的N倍。% A& i& H, u, |6 L% h0 R9 {

7 E* I8 [8 i+ b& B/ Z1 }/ U. b: `3处除以N又作为输入,当1和2的频率一样,就锁定了。(之所以图上是xN,因为从2看向3的)
7 C2 Y, [4 L. o6 U
1 T) @: G7 K* \1 x9 y# b: T; e5 s& ?/ d( c- j/ }% R8 x3 f  ]

4 ^1 \8 q6 e  M; u) k' z04 低速外部时钟(LSE)
, c  @( q+ @3 V  u
# U) b8 l. D" D+ |3 `LSE是一个32.768KHZ低速外部晶振或陶瓷谐振器。
: G( H# M7 G; m8 |3 K
) K- t' {& s2 {0 H9 y6 N1 e它的优点:提供低速但是高精度时钟给RTC外设,为时钟/日历或其他时间应用。
* E4 L, Q' ?: P5 `' C/ G, B
9 G$ U. I+ F0 U2 m* O
" n8 \4 R% @' H/ K/ s# S7 N/ L05低速内部时钟(LSI)
& ]8 I; X# |" J) K; N9 h4 l$ V( X: E6 h0 }! l
LSI RC作为一个低速时钟源,它可以运行在停止和待机模式中给独立看门狗(IWDG)和自动唤醒(AWU)。它的时钟频率在32MHZ左右。
& x# Y& U) j* s- Y
  e( D  A# y3 L4 u/ ~02、代码分析0 C# f# F, s8 \! G
时钟初始化代码在system_stm32f2xx.c文件中,大部分时候我们不需要修改时钟代码的,各个总线的频率我们可以在文件头看到。# V' f3 `- C; ~
2 b# o5 `% x  K& |* e
  1. =============================================================================( @& S( C: o. E! N, v  F3 ~1 T, ~
  2.   *=============================================================================/ `+ E5 b4 p4 ~  {8 F, h; \& S' f. }: `
  3.   *        Supported STM32F2xx device revision    | Rev B and Y% W: m7 L6 x: `# q: W" ~
  4.   *-----------------------------------------------------------------------------; `3 ^  g/ z# M* o" G& H
  5.   *        System Clock source                    | PLL (HSE)3 S/ m7 n) j# }5 ?
  6.   *-----------------------------------------------------------------------------
    : [* j3 A3 {$ k
  7.   *        SYSCLK(Hz)                             | 120000000
    " @; y4 k3 b8 K3 s: E! R4 S) I3 U9 m
  8.   *-----------------------------------------------------------------------------
    7 E! w, u/ E2 B! X  R+ S( I4 L2 w
  9.   *        HCLK(Hz)                               | 120000000% w; k3 ^) L' `  ~1 J  J9 ]: s
  10.   *-----------------------------------------------------------------------------' W' J/ j0 H" K! Y
  11.   *        AHB Prescaler                          | 14 I4 u6 T5 p2 G) v
  12.   *-----------------------------------------------------------------------------
    8 s$ X  s# n2 `2 }! G
  13.   *        APB1 Prescaler                         | 4! O, e2 D8 Q5 c6 i6 V
  14.   *-----------------------------------------------------------------------------/ p$ L+ D# _8 i" o4 w' J! Q. M
  15.   *        APB2 Prescaler                         | 2
    " c/ r; G% ?% V* f" {/ G$ O
  16.   *-----------------------------------------------------------------------------7 G' e4 s; [# |3 V8 U% _
  17.   *        HSE Frequency(Hz)                      | 25000000
    , Q, |! [1 W8 d
  18.   *-----------------------------------------------------------------------------' Y5 h! Q8 N) f' `0 q# l
  19.   *        PLL_M                                  | 25/ K; n4 F& N' O( _' m: x
  20.   *-----------------------------------------------------------------------------$ Z- \' ^$ z. D5 Y) a9 m* c
  21.   *        PLL_N                                  | 2409 E0 b7 |2 R6 B$ u$ ?
  22.   *-----------------------------------------------------------------------------
    , D: T( z1 _( P8 s
  23.   *        PLL_P                                  | 2# ?6 j/ e3 Z# O
  24.   *-----------------------------------------------------------------------------1 {5 a+ @8 _' P* ], b
  25.   *        PLL_Q                                  | 5( u; T0 G& A+ v5 O; a0 t
  26.   *-----------------------------------------------------------------------------
    : b1 U! H' L0 K: G+ d
  27.   *        PLLI2S_N                               | NA/ f2 B2 u. ?2 u7 i, Z' ?, R
  28.   *-----------------------------------------------------------------------------
    ; d3 m, j, T3 F0 o/ C
  29.   *        PLLI2S_R                               | NA: Q5 N" u; B  u
  30.   *-----------------------------------------------------------------------------& E- j6 H" f( ?3 D
  31.   *        I2S input clock                        | NA/ @2 T* A; e, B2 M. d! \* o+ T
  32.   *-----------------------------------------------------------------------------% E, L1 m- K) r' q+ O
  33.   *        VDD(V)                                 | 3.3- D; U" R. q8 A. C# q
  34.   *-----------------------------------------------------------------------------0 g) M! i8 p5 Q- ]
  35.   *        Flash Latency(WS)                      | 3
    , s9 m: Q# e1 U3 L- P/ w
  36.   *-----------------------------------------------------------------------------8 u, h  k( N& H
  37.   *        Prefetch Buffer                        | ON
    & W, W0 v7 l6 T8 _
  38.   *-----------------------------------------------------------------------------5 b6 _' I3 g, T/ k
  39.   *        Instruction cache                      | ON: N) s7 G! i0 N  s4 C. T% l  D
  40.   *------------------------------------------------------------------------------ j* d0 ?$ H( p2 w! e0 V" f
  41.   *        Data cache                             | ON
    3 f% [; d/ @. T
  42.   *-----------------------------------------------------------------------------1 b( D8 }8 t1 \
  43.   *        Require 48MHz for USB OTG FS,          | Enabled
      i# _! }4 d0 L* q8 U
  44.   *        SDIO and RNG clock                     |" ]6 F* n, n, W- B) n# Z3 O
  45.   *-----------------------------------------------------------------------------
    / E" Q2 T' ^. G; K% ~  J# R: A
  46.   *=============================================================================
    ' ~" k- ~+ g  @9 _0 d2 P
  47.   ******************************************************************************
复制代码
在文件开始定义的有系统时钟频率的全局变量SystemCoreClock,其他地方需要时钟频率,可以直接使用该变量。
$ `9 @- T" _% r. }7 |! a+ m  t2 E
  1. uint32_t SystemCoreClock = 120000000;
复制代码

  k1 ^; B0 t: l- `% F时钟配置从SystemInit函数执行,调用SystemInit的在汇编文件中startup_stm32f2xx.s(Keil编译环境)。
: y' A/ R$ e5 m6 A
5 e7 `1 o( M! c8 D1 g8 Z6 y
  1. IMPORT  __main
    1 A' N) E3 g& \
  2.     LDR     R0, =SystemInit! W. F% s+ P, \- ?5 Q
  3.     BLX     R0
    2 D, p: g- Q& B, T1 c6 w/ Z/ t
  4.     LDR     R0, =__main& n$ m" J9 y+ o2 b, l4 S, k9 _
  5.     BX      R05 ?0 N, p* ~- m3 k
  6.     ENDP
复制代码
) O0 Y7 S( A4 a' @) o
在这里说明一下文档版本的问题:
9 N, d( E/ X! {2 `) z9 q
2 y8 o' r5 U+ X. f! _3 I8 y
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

* r/ t' Y: `5 G
' c: o( |* x+ u& \. ~$ g+ w: Q▲STM32F20X_User_manual的V7版和V8版对比图1 q0 k% c, T9 f. W. m/ h5 w

5 P9 @$ }' p' a6 _% e* o上述两图的区别是系统最大时钟从120MHZ变成了168MHZ,我的理解是同样是STM32F20X,ST由于技术进步或其他,使得新版STM32F207芯片超频支持168MHZ。
8 d: `* L5 f- M( k; t, S2 x1 Z  h5 A2 [7 W9 ~1 T0 r5 C! W- r
下面我们主要分析SystemCoreClock的120M时钟怎么从一个外部25MHZ的HSE得到的。
5 c  e+ r: |4 J1 _0 n5 j, Z, l! \& }% c4 ?6 S: J! n
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

7 w9 x& u( M/ u4 ~. j6 ?
" Z; w3 p  @2 `3 X; ~9 U我们要从25MHZ的外部时钟得到120M的系统时钟,需要上图中标注的重要4点:' R  T! @* W5 [# \0 h, c2 A
" G# X) `4 V4 O& b3 T/ ~
1、使能HSE
2 f/ `9 |( y8 q
' p7 S' E0 h: g* ^# c2、选择HSE作为主PLL的输入时钟7 G+ m# y# ]2 L  M, g* T

. y9 z/ e0 z/ K9 [% W& B3、主PLL倍频后得到120MHZ时钟
$ D+ s, I4 I6 g+ W) ?' a2 r
! N0 J- C) c$ I4、系统时钟选择主PLL时钟输出作为系统时钟, A$ [5 `& f. X; J

- W5 d3 J' y0 \8 b我们找到对应的代码
/ m/ D+ {  o# t, g$ C/ Q' k- B# P; n6 b8 C7 B1 |
  1、使能HSE) p/ ?5 `* y) I  M: |3 R. w
  1. /* Enable HSE */
      ^+ }5 ^0 |% K- H
  2. RCC->CR |= ((uint32_t)RCC_CR_HSEON);
复制代码
& W; T) O/ u3 v, a% O
在RCC_CR寄存器(RCCclock control register RCC时钟控制器)中,有打开HSE的控制位" b& h; T. R  f
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

. q* g: W1 C, V7 c6 x+ f" S. L# V8 C0 v2 m( ?- b1 O7 U
2、选择HSE作为主PLL的输入时钟
6 Z% H& X0 `, J$ h
  1. /* Configure the main PLL */
    - c$ v9 x2 I1 D6 g, Z0 Z+ P
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |. M  p; S9 q) N$ e' h
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码
5 L3 p1 W( C7 |! g" C) q4 h" I7 |9 h
RCC_PLLCFGR_PLLSRC_HSE就是配置HSE作为主PLL的输入时钟
& C- l, H$ I3 E! M) s4 _  I( k! H- l  b3 J
  3、主PLL倍频后得到120MHZ时钟  q/ T5 M6 h+ k+ X8 z
  1. /* Configure the main PLL */
    . R% C6 K, X" N0 Z) B* o
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |: w% |$ D7 H# G2 Z/ G5 m, w8 B( ^
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码

: L( U4 N! \8 `2 Q# e1 i4、配置主PLL作为系统时钟的输入时钟& [+ e  [9 R  T' v3 U' ~5 w6 a
  1. /* Select the main PLL as system clock source */& `1 z/ V% [$ W% L2 J. H
  2. RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));9 G$ ^* l% |( }: h, t
  3. RCC->CFGR |= RCC_CFGR_SW_PL
复制代码

5 ~+ ~7 v- |, Y" f对于主PLL的配置寄存器,在RCC_PLLCFGR寄存器中有说明
8 j! q$ C+ g5 ~1 e! M
2 C5 |% P' |; X; `" t+ r
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

* s; ?$ e  e4 O) V9 U2 z
% e$ r; P, d3 w9 t" v) g整理后得知f(out)=f(in)* N / M / P5 ~$ T3 W- B3 ]# Z& Z% |
  1. /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
    ( U. Q- C8 S# i) }& g& {# o7 E
  2. #define PLL_M      25( r( G) l  a7 F8 _, z1 X8 K
  3. #define PLL_N      240
    ; o2 }$ y4 O  h0 O  [8 f: C5 c
  4. /* SYSCLK = PLL_VCO / PLL_P */& A) }1 F/ d( U$ s- P
  5. #define PLL_P      2
复制代码
" a7 ?0 H5 g0 g) E  g, p( d
这样就获得了120M时钟+ `3 B' U9 y7 Q$ u

  D0 j0 T) D) F$ E注意:
! C) k% O0 d& B- f! D2 s+ R. Z% I
# d% i! w* ^& j3 `
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

. V' X1 i6 k- w9 I1 e
$ i! ]7 G! n; A5 |; z1 k# DPLL_M大于等于2且小于等于63! r/ L/ ]& ^6 X; }/ [) W

/ @4 \8 B/ W' b1 J& H
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

9 H% q4 u- ]" U( E$ d& q$ q/ F
& g$ I, {7 Q5 N/ ]/ K3 ePLL_N大于等于64且小于等于4324 x! I5 h3 U$ |+ P9 x
7 q1 c  K, _' T. `7 m1 }2 v. Z
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
/ C& C5 i7 E8 J

: Y- u) \, H2 T5 h- LPLL_P只能是2、4、6、或8/ N" p+ U  u! E% G, z; v

5 Y2 p' G2 Z0 L& t9 R+ P- z  O但2对应0,4对应1,6对应2,8对应3。4 f( ]( V6 W0 \  [1 j1 i2 q
, w4 d0 A, ]# V& D
ST并没有使用if或case语句判断,因为对应的数据除以2减去1就是寄存器这两位的值,所以可以按照下面这样写,这种写法值得我们学习。: H/ ?9 a4 n8 h7 Q5 H9 p0 e1 j
( z% T; o; C' p9 O" A$ A) C2 `( u2 P
(((PLL_P >> 1) -1) << 16)$ R% y5 |: c/ |5 E" q) m6 X* f* |
其他外设的时钟配置时1 X, d2 B: A0 J' N% g: b  x) T
  1. /* HCLK = SYSCLK / 1*/6 q! u# e* H. y" h
  2. RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
    ( s$ ]0 I5 V6 X8 f# w7 O6 J8 K7 H
  3. /* PCLK2 = HCLK / 2*/. t/ h, F) K( D1 Q/ s' ~# Q
  4. RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;! n* N3 ^4 e) V3 U2 P$ ]
  5. /* PCLK1 = HCLK / 4*/0 w/ a# F3 S) ~3 w+ a0 s) u& g. T
  6. RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
复制代码

! B- f- V# v- O5 ^) J) s* v" f03、备 注
* @, h) l1 U* S, N
时钟中断8 T8 e7 M; e. {

7 C9 S5 d+ ?# `+ }) ~; X
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

) J8 Y" _7 ~0 N
8 @0 `4 J/ }; l7 b5 f- j- w8 y  b可以配置外部晶振出错时的中断,还有RCC中断,因此我们可以在外部时钟出问题时,切换为内部时钟,不至于整个系统挂掉。具体见ST给的官方代码。
' c/ S; U# i: N: o$ b$ `( K7 j* g7 y1 F! M
无源晶振不起振
6 V5 h. N0 e4 ~8 ?9 E
2 q; s8 c9 w  @5 E2 i没有程序,无源晶振是不起振的,需要配置RCC时钟控制寄存器的HSEON位打开或关闭HSE振荡器。具体可以看之前的文章《晶振原理解析》。
- W, n/ J! p3 s% d! {# x: N; n% C+ y' ^- H! I
关于APB和PCLK
% T) J3 U) [- F6 ^; K
, ?; L. U/ W5 d( E8 ]
F207是时钟图没有显示PCLK1和PCLK2,应该就是APB1和APB2
1 J# a, f" h/ E/ T8 H2 g# Q3 K/ W6 F- P. z
应该指的是一个PCLK应该是PeripheralClock的简称,看F105手册
) K/ F# r9 [# L: D, L
' ~/ I3 a( D9 U3 s4 @. z+ {
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.jpg
$ Z/ e& p0 `2 Z( o7 ~& O1 M( G
: P* l, v" x1 ^8 i# C" _5 C6 I1 J
- z0 Y7 N+ F4 l) f) \( |
8 `7 M7 @0 T6 L  u9 |/ u

/ Z7 V$ _7 i) n% _  @! K; _0 a& ]1 j

2 P- D* p4 ~; y3 g0 K, z/ }- v" I2 @! Z
收藏 评论0 发布时间:2021-12-3 17:00

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版