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

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

[复制链接]
STMCU小助手 发布时间:2021-12-3 17:00
板子使用的是25M无源晶振,下文将介绍STM32F207的时钟系统如何将25M晶振时钟转换为120M系统主频时钟的。
, w( w! G* q) [
) e2 b0 F7 H5 f7 m) s6 [01、时钟系统介绍: `9 @2 P& I+ T3 _& j) L4 u1 u

5 G  P+ H3 p9 j
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
/ o& p  A* d1 K9 Q
                                                                    ▲时钟系统专业名词缩写* m7 D, n" o4 f: f8 M

# _9 i) C8 ?0 p1 C1 m# j时钟系统关键组成部分
) N: }1 O; m+ r/ z3 \
: h$ R  d6 t% u% F; I: j01 内部高速时钟(HSI)) g# [- j, E1 o& b4 o0 t# H$ o
5 L1 W4 o3 q5 d! C& c8 E; e5 J
HSI时钟信号可以通过内部16MHZ的RC振荡器产生,可以直接用于系统时钟或者用于PLL输入。
: X& J" o: M! M4 @7 i0 l  X
$ S' {2 `& t5 p" o6 ~* T- o  A# DHSI的RC振荡器的优势是:在最小成本(没有外部器件)情况下提供一个时钟源。它的启动速度要比HSE晶体振荡器更快,但是即使校准频率后,它的精度仍然小于外部晶体振荡器或陶瓷谐振器。- }. h, t' `/ K. H( E, K" o+ d

# i, v( d3 Y& c02 外部高速时钟(HSE)
7 y3 i; R7 I: Q% D
" t, Y& ?2 }- C% s2 K, a$ V$ i% a% W外部高速时钟信息(HSE)可以通过两个时钟源产生:
" }0 |# H( j" m, r+ a0 x6 U! `; \+ N
① 外部晶体/陶瓷谐振器# i9 _9 W  H* e
: P0 V! G  G* U$ v0 E* s( }
② 外部用户时钟+ q$ F1 F7 D% V* P2 Y, D* ?+ y/ D

1 Q9 @6 Q$ y) _5 F8 Y5 R
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
% C* `( i" }9 d6 o$ y( p9 S, A9 W

2 Z0 R) p- n( q, j▲两种时钟源接入示意图) c/ t3 b1 u) N8 V! q7 x! b, J: i

) w! f$ t8 H) V( x
! b. h( [/ O) E: k03 主锁相环时钟(PLL)1 {, O8 H+ y. d  L: x$ \' N

4 V4 q/ u1 Y4 ]( i6 ^STM32F2xx具有两个PLL
  ?3 p; c  ~6 Q7 g0 y" J
% Y  n8 T/ m1 z0 Y① 主要的PLL通过HSE或HSI提供时钟,并且有两个输出时钟;
" E) d2 Q  g+ W- I: E, T/ }" Z$ K  H; ]
② 专用的PLL(PLLI2S)被用于产生一个精确的时钟去实现高质量音频效果在I2S接口;
0 \. ?" D& h+ {4 T9 m$ N
' l. q5 @! R9 O7 d) c. w/ v* u
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

0 W  V$ {  V2 s3 a; T" |! }& _' s) j4 t9 ?4 `: z- D
# W8 _2 a0 F1 ]: q$ u  v
HSE/M*N/P得到PLL时钟% j5 W/ |) F0 U) Q

4 x. K7 [0 _$ V关于PLL锁相环说明
. e$ s; I/ t0 i; \9 V# p& c
; v" e2 t! V* w5 }! O+ r& p; f0 F
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
3 a+ F% o. p% `+ H7 Q

2 o; D' e+ S4 D
; i7 b3 S& U) \9 a从1处输入,3处输出是1的N倍。
* c9 K% g, y, I' r
3 e( c5 L5 Y6 X- p9 g* U3处除以N又作为输入,当1和2的频率一样,就锁定了。(之所以图上是xN,因为从2看向3的)* Y& @% m' f( F& P- h" |

4 E/ I2 c' M" p: w& O5 i, q( s  h& j
* t$ j4 k9 O# e  L4 Y
04 低速外部时钟(LSE)  T( A8 {+ W. F$ S7 c
9 u  J& b9 B5 i) y
LSE是一个32.768KHZ低速外部晶振或陶瓷谐振器。
+ t* @. A  P9 A6 i
# A% Z- f8 f( I% H9 W它的优点:提供低速但是高精度时钟给RTC外设,为时钟/日历或其他时间应用。
$ E6 v2 s6 D: K* p" j7 I3 R
/ D& r9 X. `5 |# l$ Z8 s7 O, G9 m# N, o7 t& M* W1 c, W) w
05低速内部时钟(LSI)$ G- O+ S& {. O  c- M& J7 P* b
& u6 c. M4 j! Z3 N
LSI RC作为一个低速时钟源,它可以运行在停止和待机模式中给独立看门狗(IWDG)和自动唤醒(AWU)。它的时钟频率在32MHZ左右。
* E6 d$ S' {/ S9 M* `
- [5 ]' I/ v- @) a5 H. c8 L: L02、代码分析$ V) t( W7 b& U' T
时钟初始化代码在system_stm32f2xx.c文件中,大部分时候我们不需要修改时钟代码的,各个总线的频率我们可以在文件头看到。
- Z. H' }6 R7 Z
8 p" x, [2 p& t& p8 e0 r: s
  1. =============================================================================% a& n$ g4 H) v0 i1 W- E% @$ v; H
  2.   *=============================================================================. k9 h2 o" @0 m- L
  3.   *        Supported STM32F2xx device revision    | Rev B and Y
    & H- m+ Z; N2 Y& x8 Z" ?5 ^0 K
  4.   *-----------------------------------------------------------------------------
    9 I% f% u4 \- d) g- s, X/ n$ i
  5.   *        System Clock source                    | PLL (HSE)1 \' F5 e& U/ j
  6.   *-----------------------------------------------------------------------------
    ! `) U( l- z/ T% z! ~( |
  7.   *        SYSCLK(Hz)                             | 120000000/ N" ?, E# M" P0 j+ Q1 h
  8.   *-----------------------------------------------------------------------------
    + L6 l* i5 A2 R# ]  U: _
  9.   *        HCLK(Hz)                               | 120000000
    1 S2 X1 t7 p: }; z* c6 U6 \
  10.   *-----------------------------------------------------------------------------
    : d; h5 J9 R! F2 A0 N
  11.   *        AHB Prescaler                          | 1
    4 q+ O# p5 t: U$ r3 l
  12.   *-----------------------------------------------------------------------------# [# N1 P. b+ e# o/ Y1 B8 v
  13.   *        APB1 Prescaler                         | 4
    1 A0 _; y# x) x( S% P
  14.   *-----------------------------------------------------------------------------  s8 w0 v) y3 B+ F
  15.   *        APB2 Prescaler                         | 21 i2 N/ F5 K. r  K# n' w
  16.   *-----------------------------------------------------------------------------
    $ u, s' _2 i' n: I& ~! o! D
  17.   *        HSE Frequency(Hz)                      | 25000000. {. j+ Y! o/ f2 X% x
  18.   *-----------------------------------------------------------------------------
    - {* K& |+ Z. ~( Y! S+ C' b
  19.   *        PLL_M                                  | 254 U5 p. m9 Q. a) O& \% G2 l
  20.   *-----------------------------------------------------------------------------
    . q) c; F+ P( F& S2 k
  21.   *        PLL_N                                  | 240: w/ x+ R8 G. h! b
  22.   *-----------------------------------------------------------------------------! r% n  Y1 N$ b  }- e
  23.   *        PLL_P                                  | 2
    9 m+ K6 s9 @* }4 e0 J0 a
  24.   *-----------------------------------------------------------------------------
    / p  S& v; y5 u
  25.   *        PLL_Q                                  | 54 D4 N) x: K8 \: t: B
  26.   *-----------------------------------------------------------------------------# @  c- S6 Y7 K" n- l
  27.   *        PLLI2S_N                               | NA! p4 q" E) j% Y
  28.   *-----------------------------------------------------------------------------
    6 G9 b' e" b: k  K0 y8 {' N
  29.   *        PLLI2S_R                               | NA; P* c, ~5 u) U- r; s3 p8 l
  30.   *-----------------------------------------------------------------------------/ z8 q4 v6 v, F0 K+ N
  31.   *        I2S input clock                        | NA
    7 n+ M# F7 B/ d. e) Z/ p3 W" D
  32.   *-----------------------------------------------------------------------------
    / k5 E: B! x3 V9 C
  33.   *        VDD(V)                                 | 3.3- r7 P# k( ^9 Z' f% G. X9 f/ U( j5 E% L( Z
  34.   *-----------------------------------------------------------------------------! {/ c' j# C$ |: g! V
  35.   *        Flash Latency(WS)                      | 3
    / u# C" t* s* Z; r6 H+ v- G( J) v
  36.   *-----------------------------------------------------------------------------" v3 i# z3 ]1 U
  37.   *        Prefetch Buffer                        | ON
    ( |' l$ W7 y4 R* c
  38.   *-----------------------------------------------------------------------------' v, @9 g, w: Y8 f8 r, p4 |
  39.   *        Instruction cache                      | ON
    # E/ F9 \# _+ V. _% S/ y" R' C* l
  40.   *-----------------------------------------------------------------------------# ~& `! w  N& X* B4 C# q5 G/ v
  41.   *        Data cache                             | ON
    : _! d6 t" q8 p6 S8 I# Q
  42.   *-----------------------------------------------------------------------------
    ) ~) Q1 G" z+ W; u$ y& D' w
  43.   *        Require 48MHz for USB OTG FS,          | Enabled1 U" [* T1 Z! t: L+ a: h# k
  44.   *        SDIO and RNG clock                     |
    ! T5 I/ m, ?+ I# S4 x& |9 N. {& u
  45.   *-----------------------------------------------------------------------------
    / q) Z; ^# H; L* ]; B
  46.   *=============================================================================+ M, L) v8 v4 s: C) f0 ^- a+ H( k3 d, A
  47.   ******************************************************************************
复制代码
在文件开始定义的有系统时钟频率的全局变量SystemCoreClock,其他地方需要时钟频率,可以直接使用该变量。$ o1 d) |8 V3 r' B
  1. uint32_t SystemCoreClock = 120000000;
复制代码
6 ]  m2 L8 L4 D2 L* F- h  I
时钟配置从SystemInit函数执行,调用SystemInit的在汇编文件中startup_stm32f2xx.s(Keil编译环境)。& H/ ^$ K0 u" r7 k  |

4 {% J* R; B2 q% \7 O
  1. IMPORT  __main) u3 P4 O' _* p; x$ Z
  2.     LDR     R0, =SystemInit
    . |2 {2 w7 X" U# p' C0 E8 k( j
  3.     BLX     R0& |9 ^9 y1 S, K' e
  4.     LDR     R0, =__main
    / V+ |4 {/ n  x0 W7 u# i
  5.     BX      R0$ \% D" w; ?# _" ~: K$ q* p
  6.     ENDP
复制代码
( m5 K; _  G$ E$ w  y5 W  }  g
在这里说明一下文档版本的问题:
, i# ~* g: n4 R' A3 o6 k5 s/ v4 Z+ B* V9 A3 o  k& S9 E( Q
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

2 ~5 b0 a# K* n
! [- d! A1 H! C8 `$ v▲STM32F20X_User_manual的V7版和V8版对比图/ e/ e8 k7 [( s1 p6 a/ L
/ d9 _6 L. z4 C) M3 B
上述两图的区别是系统最大时钟从120MHZ变成了168MHZ,我的理解是同样是STM32F20X,ST由于技术进步或其他,使得新版STM32F207芯片超频支持168MHZ。
* ?4 b8 Q: e- [3 e8 H- z
- Y9 H) C: J% m2 ]( G: A下面我们主要分析SystemCoreClock的120M时钟怎么从一个外部25MHZ的HSE得到的。! z$ \8 W8 S& u" N% s  c+ o8 n
1 d4 q* _7 c+ S8 Q5 m# y4 j: k0 @
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
0 y2 o4 F0 d3 I5 `9 ~9 A1 X

/ i7 E# P# ]/ B+ N( \9 |4 p6 ^我们要从25MHZ的外部时钟得到120M的系统时钟,需要上图中标注的重要4点:5 a" t9 g" G0 ?8 G
  @- F8 y9 q8 E+ V# O7 @" X
1、使能HSE
  h6 Y( }" O; }5 w# A% }
* _% c$ v, t) L% q2、选择HSE作为主PLL的输入时钟5 z! u! y( A5 T2 I. W4 {
- R- ?! U! k, h) |" N9 i
3、主PLL倍频后得到120MHZ时钟
0 n+ v7 i+ h/ i9 ^) }+ x1 t
* ~9 }- R0 i0 ^; S9 N4、系统时钟选择主PLL时钟输出作为系统时钟
* M$ c6 a/ D7 x) x1 m8 [& o- D/ b, {# ?) ?7 K
我们找到对应的代码$ h- Y$ w4 {) y9 e

3 l) f+ A9 K: s& Y! J- O  1、使能HSE' k0 F9 K6 |5 W/ G7 L4 Z" b/ `
  1. /* Enable HSE */
    8 d% d6 b) E; V$ X' ~
  2. RCC->CR |= ((uint32_t)RCC_CR_HSEON);
复制代码
3 |' x' u- F+ b. z4 u
在RCC_CR寄存器(RCCclock control register RCC时钟控制器)中,有打开HSE的控制位
. R8 e$ d+ ^: ]: X
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

7 C1 L; u3 n1 e0 R5 D+ {0 `" _- s* S0 \; i, J5 V* T( |
2、选择HSE作为主PLL的输入时钟- S, m% p- y. e2 I
  1. /* Configure the main PLL */3 m8 m* C8 n/ C, d
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |( w  j9 M7 s( F
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码
# I% E% u+ M( r6 N4 E" C$ z
RCC_PLLCFGR_PLLSRC_HSE就是配置HSE作为主PLL的输入时钟9 A- p8 u2 r- J1 l3 d

+ r  j8 U5 K5 W$ O  3、主PLL倍频后得到120MHZ时钟" s4 ]* v- ~% h% v7 V. y; v
  1. /* Configure the main PLL */
    ; |% x4 o& Y2 a2 v. A+ s
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
    3 A1 g0 f/ B# O1 y5 p& ]/ K* a
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码

( R* E4 L' D" @  i9 f/ `4、配置主PLL作为系统时钟的输入时钟7 k5 }2 X9 Q/ d
  1. /* Select the main PLL as system clock source */& R; ]0 r& Y' L
  2. RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    : e9 q- X+ P5 K1 S! J/ [
  3. RCC->CFGR |= RCC_CFGR_SW_PL
复制代码
) o* B0 \$ n7 v: _* O& `
对于主PLL的配置寄存器,在RCC_PLLCFGR寄存器中有说明7 O2 f( E2 @: _4 ~# ^! K$ F

! K* M6 H7 p, W0 l
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

% ~& ?9 R8 T! R% a% n' _6 `9 U4 e' }1 B. q4 |. t& A
整理后得知f(out)=f(in)* N / M / P* K- F- G) u" K: t( _
  1. /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */  U, [( B( |0 N
  2. #define PLL_M      258 e$ u: w% P1 j% N9 d$ e1 L
  3. #define PLL_N      240" x% h+ i% }0 Q0 X5 L
  4. /* SYSCLK = PLL_VCO / PLL_P */% h) w' p+ F- v( Z1 B
  5. #define PLL_P      2
复制代码

5 {% v/ [' N5 W. \1 K8 F这样就获得了120M时钟
! Q  K8 m; X  \4 R( J2 c6 D4 u) [% F
注意:5 Z& _& g  I4 f0 S

7 ?0 B5 C7 r% n  C. x
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
( r+ F& ?' {% c# B5 `! K2 Q

# B6 D  x* I( F6 b% ?8 |PLL_M大于等于2且小于等于631 s6 i$ e  W2 {6 p
. _' ~. l1 D& o$ V4 A6 H
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

) O# h) V2 o2 B4 Z: Y* F# a( R  d! f6 A$ M' ^' U' f, {
PLL_N大于等于64且小于等于432
# ~6 M" g9 U0 U# b/ ~$ _& \1 j+ A( h: F9 F. D
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

! K  t8 u/ m7 m) b6 [; x. c# u' C) f/ k" m2 E" O4 E
PLL_P只能是2、4、6、或89 i  P* Y' M2 Y' {3 }$ V

3 D7 e8 o8 m6 i/ M+ w  t但2对应0,4对应1,6对应2,8对应3。
* T+ p: u! T  R# W% X0 M+ N9 Q$ ]( W7 y
ST并没有使用if或case语句判断,因为对应的数据除以2减去1就是寄存器这两位的值,所以可以按照下面这样写,这种写法值得我们学习。1 k9 ^& X2 @2 [1 r8 r

6 `0 Y/ \9 E$ V: a# d(((PLL_P >> 1) -1) << 16)$ A1 J6 v4 H4 j% [
其他外设的时钟配置时
! \! J. Z3 Z( y" a& |) X7 O* M
  1. /* HCLK = SYSCLK / 1*/
    2 N7 ~7 @+ @) m" {4 z9 ?
  2. RCC->CFGR |= RCC_CFGR_HPRE_DIV1;& W: [9 n" H6 Q: t7 |
  3. /* PCLK2 = HCLK / 2*/
    5 x! Y5 g0 F2 {
  4. RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;; }& ?7 _6 i2 T) C% H5 n5 O
  5. /* PCLK1 = HCLK / 4*/
    8 i. q5 }1 d' j# F
  6. RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
复制代码

4 o: x7 G* y0 l; h03、备 注

2 }  x( r# y7 T时钟中断
% g' ^5 I3 b! P1 P; q: [
3 s$ r# M* [* [# y$ Y0 l5 Y
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

% e: k+ W6 u* n- T, Y# e3 r) G" v7 N  f5 L0 o- X  A
可以配置外部晶振出错时的中断,还有RCC中断,因此我们可以在外部时钟出问题时,切换为内部时钟,不至于整个系统挂掉。具体见ST给的官方代码。4 I  X0 d1 @$ i8 \% [2 e
, c8 k' G, {4 t. L6 v
无源晶振不起振0 g4 C6 g( P; S5 l3 O! E

5 ^3 h0 T, m5 L: q- H; p没有程序,无源晶振是不起振的,需要配置RCC时钟控制寄存器的HSEON位打开或关闭HSE振荡器。具体可以看之前的文章《晶振原理解析》。
( a2 h& m: F3 a4 {
: t: Y! k& t7 M  f 关于APB和PCLK
- c0 j' n1 D2 T) R5 W

. o" Y; `1 j0 }F207是时钟图没有显示PCLK1和PCLK2,应该就是APB1和APB2
1 C1 n+ V! [. S$ `1 L( v- D) T" x4 ?! n2 I; w( n
应该指的是一个PCLK应该是PeripheralClock的简称,看F105手册: R3 x" O9 Z* K$ v) f

6 l! S) {, X' R6 m0 M, k  O  n
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.jpg

9 p) K) z5 l7 x% d" V7 g) W$ D  f$ w  v4 T5 w2 H& Z# e4 ~

' I/ k3 t3 G0 `7 S# ~8 V- l( `5 U: l8 v  g$ x: |% ^

8 y6 n. W6 W: Z' L3 V6 q+ e; n' }* c! k7 k0 s) X9 u+ n; n

/ ]( ?, ^- N" |! q0 _6 h5 u: d/ z5 y5 k
收藏 评论0 发布时间:2021-12-3 17:00

举报

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