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

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

[复制链接]
STMCU小助手 发布时间:2021-12-3 17:00
板子使用的是25M无源晶振,下文将介绍STM32F207的时钟系统如何将25M晶振时钟转换为120M系统主频时钟的。' w. v, W, C, J
$ o9 \# j- l8 ]
01、时钟系统介绍
* ]  f/ n# q7 e. k4 v6 p! l' X, E7 R' t3 d0 B
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

' k. ?' ~; b2 B! f* P  c8 P                                                                    ▲时钟系统专业名词缩写
& w0 h$ z0 I5 K4 Y4 Q# @' V
6 N1 I* l2 v8 i8 n( H; L时钟系统关键组成部分1 z) L+ ^  X. V& A" {
9 P8 q8 b9 n4 o
01 内部高速时钟(HSI)
8 W; S4 u2 ?& s& {" m6 K, w$ z. K: U7 w4 H# _2 u+ o  m2 F, b2 H' u* l! V
HSI时钟信号可以通过内部16MHZ的RC振荡器产生,可以直接用于系统时钟或者用于PLL输入。) Y; Q' f) B6 [+ q8 @" e
$ I- Y! L0 r) Y
HSI的RC振荡器的优势是:在最小成本(没有外部器件)情况下提供一个时钟源。它的启动速度要比HSE晶体振荡器更快,但是即使校准频率后,它的精度仍然小于外部晶体振荡器或陶瓷谐振器。  K/ z9 h; l3 e! l9 V  J+ T
7 E& J6 G  |5 m* J
02 外部高速时钟(HSE)
0 D1 H7 c+ X9 _  V
5 |9 Q. W" `8 c! Z$ \# d* g/ k# Z外部高速时钟信息(HSE)可以通过两个时钟源产生:( ~1 d0 E3 G' K
# y. p0 L( g; g6 W- [4 i
① 外部晶体/陶瓷谐振器8 H( y: j- X  X5 f4 ~! y1 R
' `& n9 i  q" P4 L
② 外部用户时钟
) n. M% I: U7 C  J4 ?; T
& A* D( z9 ^( C) s
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
  Z6 y* P. V( Z3 {: k9 {
3 c& Z8 A8 h' B8 R
▲两种时钟源接入示意图5 K" r' L2 C' Q6 ^( C$ o
  I' e* v5 M) ]8 m

0 D8 V7 H6 U% ^03 主锁相环时钟(PLL)& z2 ]4 e& ~% d% M" E3 ^. [9 u

( s6 `& ^6 z! w& D; a2 hSTM32F2xx具有两个PLL$ I, |. r) r0 J# F8 A

) J0 P3 M1 C$ C& `9 |, f, J① 主要的PLL通过HSE或HSI提供时钟,并且有两个输出时钟;
% H5 Z8 c  o2 y, p" f
. P* f- Z6 j; N5 W+ l3 |② 专用的PLL(PLLI2S)被用于产生一个精确的时钟去实现高质量音频效果在I2S接口;
0 [. v6 x" r0 @' Z! ~4 a( Q! V* J3 L. A& s9 W; N% W3 C( O
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
1 R9 G1 q* m7 B; @4 w0 h$ Q! H9 v

' _; Y) n& A( ~9 Y/ `% @  S! {9 n: I* j( F
HSE/M*N/P得到PLL时钟
: m+ k" B8 k2 G7 o( T/ T4 ^% X3 T$ B4 T7 V6 T, k9 o" v
关于PLL锁相环说明) G: H0 R* P( L, \- m7 ^4 g- Y( U

/ F+ p7 O& T/ e8 ~/ A1 I
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
1 x# g6 e/ s7 s4 ~# T

; ^% J3 @, }% y1 t" Z5 `: t' m9 y; j: V/ W' F8 g3 c+ t* J
从1处输入,3处输出是1的N倍。( C- i7 q5 L8 \% s& X4 \

5 n0 n- p: Q* p( Q: q+ o3处除以N又作为输入,当1和2的频率一样,就锁定了。(之所以图上是xN,因为从2看向3的)# I0 b  I# t7 f4 i4 L8 j
( m$ R6 \( c6 M$ A8 q

& J. l0 W1 @% S6 r" `1 q% o: m  O
: s* P8 ]3 ^* r, I+ O( u04 低速外部时钟(LSE)
) Z; u. N) a: H5 ~1 I# v
- ]2 F* t' u8 h$ X' a! g% LLSE是一个32.768KHZ低速外部晶振或陶瓷谐振器。$ ~4 M% J' G, A' _8 \
5 l& _. i0 T- U; N
它的优点:提供低速但是高精度时钟给RTC外设,为时钟/日历或其他时间应用。4 d( X; y( Q$ A: O* e! V
) Q; |2 I  F; q  V4 u- R( b2 M
+ [) V7 }( Y, P1 i
05低速内部时钟(LSI)
/ v( k- {1 y- d8 ]" m
: ?% E* F; b4 A7 C- [8 wLSI RC作为一个低速时钟源,它可以运行在停止和待机模式中给独立看门狗(IWDG)和自动唤醒(AWU)。它的时钟频率在32MHZ左右。3 w: ]6 S, h: g: P" |0 S  l5 ?0 O
2 {* a& K! G) Q) j
02、代码分析
+ T; K4 G* `, U2 |( ?) C: s- k时钟初始化代码在system_stm32f2xx.c文件中,大部分时候我们不需要修改时钟代码的,各个总线的频率我们可以在文件头看到。
: S( [8 b9 s% t& x9 U8 [0 [
" ]- X% W: p9 M% _$ S& C1 R
  1. =============================================================================' |- V- n0 m/ h2 D. D* C! ^+ D
  2.   *=============================================================================
    % z' Z& M+ Y/ D( ~% }
  3.   *        Supported STM32F2xx device revision    | Rev B and Y' E5 C/ k7 i* @" x; s* {
  4.   *-----------------------------------------------------------------------------# m3 L0 M1 }3 F/ L0 \+ H' \
  5.   *        System Clock source                    | PLL (HSE)6 |$ t% R& ~: e9 ~2 X, [3 o
  6.   *-----------------------------------------------------------------------------. A6 w9 R2 y3 u, I
  7.   *        SYSCLK(Hz)                             | 120000000$ @2 Y5 n1 X3 Q
  8.   *-----------------------------------------------------------------------------, [! `9 c# ?$ n" O- ^8 J* S9 d5 l8 W
  9.   *        HCLK(Hz)                               | 120000000- i, L4 J5 x0 }* g; G
  10.   *-----------------------------------------------------------------------------
    6 o) w9 \$ y% i# y+ h
  11.   *        AHB Prescaler                          | 13 k0 O8 q9 N+ A9 T# j: N7 e. {
  12.   *-----------------------------------------------------------------------------
      y' B( c; U% T: l1 c% E
  13.   *        APB1 Prescaler                         | 4& _  Z! C0 R3 s: _
  14.   *-----------------------------------------------------------------------------
    / Y9 r1 ^; }1 r% \/ i1 p  K. E; b+ a5 x
  15.   *        APB2 Prescaler                         | 2$ h9 A' `2 x0 N" a/ N
  16.   *-----------------------------------------------------------------------------6 e% j3 H; g5 D: n5 y
  17.   *        HSE Frequency(Hz)                      | 25000000
    + D4 T* K7 g3 s8 }
  18.   *-----------------------------------------------------------------------------
    6 y$ U: Q0 _! D
  19.   *        PLL_M                                  | 25
    # t) U6 W: h% g$ o
  20.   *-----------------------------------------------------------------------------$ R# z# g2 O( y( A6 G
  21.   *        PLL_N                                  | 240
    % _  j& @4 t4 T; |! {) I( y
  22.   *-----------------------------------------------------------------------------+ H" E: z. @. e6 w7 j. s
  23.   *        PLL_P                                  | 21 r5 X/ T8 o6 v# Z6 `& @; G
  24.   *-----------------------------------------------------------------------------
    ) y2 B9 z3 M! d+ C3 G, j
  25.   *        PLL_Q                                  | 5; b, p# }# W1 ?% y) [
  26.   *-----------------------------------------------------------------------------0 j" b+ t+ R, K8 s" T) D& F6 z
  27.   *        PLLI2S_N                               | NA7 M6 a: ~. I/ G' ]* C- W0 ]  U
  28.   *-----------------------------------------------------------------------------
      L$ ~/ k# C9 ]' u" @% Z, X
  29.   *        PLLI2S_R                               | NA
    2 @5 y5 `' ]8 a& t
  30.   *-----------------------------------------------------------------------------% i7 f  W& Y* B! b  \
  31.   *        I2S input clock                        | NA3 _9 H9 z( Y! f7 b, V5 }
  32.   *-----------------------------------------------------------------------------& X9 W9 \* e' R2 h
  33.   *        VDD(V)                                 | 3.3
    8 _( h; B$ ]  m( l7 w
  34.   *-----------------------------------------------------------------------------
    9 A+ H! Q- D% S' s% Y2 }) Y
  35.   *        Flash Latency(WS)                      | 3% ?& P5 K' L* G7 I8 Q9 d
  36.   *-----------------------------------------------------------------------------; U( Z( ^$ p  I  i& q! z
  37.   *        Prefetch Buffer                        | ON$ t0 U) a1 m/ p
  38.   *-----------------------------------------------------------------------------. k7 h4 e* t1 k0 H  z
  39.   *        Instruction cache                      | ON5 {6 `) S, n# I# b2 \
  40.   *-----------------------------------------------------------------------------( y( h/ |$ \0 |" V& d. N( V
  41.   *        Data cache                             | ON3 C! {' b. O6 _3 w' \9 K. T
  42.   *-----------------------------------------------------------------------------
    " g" V/ q' G  Q9 P( V
  43.   *        Require 48MHz for USB OTG FS,          | Enabled+ j0 e7 m6 {+ D4 h
  44.   *        SDIO and RNG clock                     |" h- U& J2 A5 q; _2 x# p1 k
  45.   *-----------------------------------------------------------------------------' K$ B, ]% J( k: p
  46.   *=============================================================================
    : j5 E% P( p4 q. J3 D7 V" u) T- [
  47.   ******************************************************************************
复制代码
在文件开始定义的有系统时钟频率的全局变量SystemCoreClock,其他地方需要时钟频率,可以直接使用该变量。
! {; P8 [) o: t0 r, |
  1. uint32_t SystemCoreClock = 120000000;
复制代码

. d: [  w* x! S4 l& e时钟配置从SystemInit函数执行,调用SystemInit的在汇编文件中startup_stm32f2xx.s(Keil编译环境)。
6 F+ ]- ~/ w) v) R& [( `2 p& c# W! o3 h& g4 ?" p2 n
  1. IMPORT  __main, v  m0 h- J+ o* W5 I6 f
  2.     LDR     R0, =SystemInit( s6 q. g) C$ W5 [+ P: p
  3.     BLX     R00 L$ `5 j( E4 w7 h
  4.     LDR     R0, =__main8 C7 y; m& i6 C2 G
  5.     BX      R0
    / c& ~2 s: J0 I) D  I- C" p; E
  6.     ENDP
复制代码

# \5 i3 i1 J2 t% |- x4 M- F在这里说明一下文档版本的问题:! }! K$ L. H" u9 D: h# E

9 v# n. s2 {7 e/ L
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
' X2 o0 ~( a8 K0 I( C6 T

+ g$ p. I) R* j  X! r& Y▲STM32F20X_User_manual的V7版和V8版对比图! M0 O$ M/ {$ W7 Z- s
" Z3 a7 J" D9 g8 f. R# h4 y
上述两图的区别是系统最大时钟从120MHZ变成了168MHZ,我的理解是同样是STM32F20X,ST由于技术进步或其他,使得新版STM32F207芯片超频支持168MHZ。( n7 Y% W6 B2 T0 l4 F( V5 Z
+ `4 {/ r. Z. ^6 ~: m7 c
下面我们主要分析SystemCoreClock的120M时钟怎么从一个外部25MHZ的HSE得到的。
. `9 R3 E% w0 M+ h4 S% R: a+ v- M" g* v
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
; S+ z! K7 q' h' m) q! N8 o
9 s- Q) s7 ~- m/ |7 F% `
我们要从25MHZ的外部时钟得到120M的系统时钟,需要上图中标注的重要4点:
7 r9 M4 O5 \5 A
1 W. b1 N0 V( m) f1、使能HSE
" b9 C7 b' p+ Q$ R2 K  U2 I, h& F- a6 V
2、选择HSE作为主PLL的输入时钟! B: w* K# h! }& |0 a. v: H) e
+ B& p4 o3 G, e' F9 }9 g
3、主PLL倍频后得到120MHZ时钟
# U; F2 n" m8 h" _$ B8 v# f
' B2 p* F* P$ a4 z# ^4、系统时钟选择主PLL时钟输出作为系统时钟
+ g5 n5 ?" c6 K5 y4 u1 ~7 y# Z' {8 {6 e$ D
我们找到对应的代码
- E7 m% a5 M1 C
. N2 v( p* \* W2 c. E  1、使能HSE
+ ~! r/ `) `/ F; @8 a$ H9 ]
  1. /* Enable HSE */( i" U. q* x8 Y. e) Q* L$ s5 Q$ u# [
  2. RCC->CR |= ((uint32_t)RCC_CR_HSEON);
复制代码

% ~! P" }# l  E0 K' U在RCC_CR寄存器(RCCclock control register RCC时钟控制器)中,有打开HSE的控制位
3 h2 o9 [  v+ D  a4 k
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

: f. i( L$ O7 W  Y, A  E
: m/ O3 B1 p7 H: N  y2、选择HSE作为主PLL的输入时钟
4 a- H4 t' l" q! O
  1. /* Configure the main PLL */3 m/ o8 j  @/ F1 b
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |" X+ k" g) x. Z
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码
. G: F4 U! m! [
RCC_PLLCFGR_PLLSRC_HSE就是配置HSE作为主PLL的输入时钟
* @+ i7 j: s# \1 ]( h, V
9 ~& p8 J+ a' i  {% n1 Z- o, }  3、主PLL倍频后得到120MHZ时钟
7 y9 s1 R# C, |0 G6 f" H
  1. /* Configure the main PLL */4 Q5 L  `! M) X3 u5 n: y3 R
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |+ E7 x* \6 C# \* K- ^& K
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码

) M+ B* b$ f* z4 R# t8 N4、配置主PLL作为系统时钟的输入时钟
' `3 g% |4 c; \! @/ N0 _( M9 m
  1. /* Select the main PLL as system clock source */% q1 p% Z" B" v/ V+ C& d
  2. RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    + t7 B( j" O* h' I: `6 ?0 z
  3. RCC->CFGR |= RCC_CFGR_SW_PL
复制代码
# b* k* Q( e9 B7 T6 R
对于主PLL的配置寄存器,在RCC_PLLCFGR寄存器中有说明* R# X* C" Q& ]
6 g: T. x- K, _- N# F
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

7 T/ S$ w" L: k% F, O- {/ _, ~
; c: ]5 V; j2 V7 T2 L整理后得知f(out)=f(in)* N / M / P' _7 F  V* Z! e* i8 Z4 c6 y
  1. /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
    / i0 o- Y! v3 I" i  `+ v: Q
  2. #define PLL_M      259 Q5 T9 @9 \8 x0 C
  3. #define PLL_N      240
    ' g$ a0 A$ |8 X# h: I* i! W
  4. /* SYSCLK = PLL_VCO / PLL_P */# Q6 E$ S, V6 u0 w4 Q! s* I: i# J5 S
  5. #define PLL_P      2
复制代码

  \9 u6 K9 E% z. |/ ]这样就获得了120M时钟
( ^- E2 E4 W% \! j; E: N9 Y2 y6 x' ]  P( L. F4 ^5 w/ J
注意:* M' r/ Q: v* j5 M1 i+ q
/ s: U" `* R! w; R# B
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

6 a" B7 w6 c/ u, B2 R) W8 y5 j) A) v) F
! m4 i$ k4 V) h! oPLL_M大于等于2且小于等于63; ~8 k: l$ t2 C
6 N. o3 O& [3 U- ]) t6 F& c7 O
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
" K) W# O; `1 l

8 q- O4 u( s7 ^4 {5 I2 FPLL_N大于等于64且小于等于432
4 k. r: Q, W. }% ^; h# T0 ^2 f) S- ^5 u+ b( v
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png

$ q  f4 m, E! O2 q) b! k2 N9 Z. m2 V9 B1 ]' H
PLL_P只能是2、4、6、或8
% Q: g& A1 W/ h# C0 J' k$ k! r6 D% t7 L: z7 z  ^: V3 R- p
但2对应0,4对应1,6对应2,8对应3。
' |' ]; E! V3 m9 E1 A5 r" e1 i- C# x5 G
ST并没有使用if或case语句判断,因为对应的数据除以2减去1就是寄存器这两位的值,所以可以按照下面这样写,这种写法值得我们学习。& H/ ]: e8 n+ i5 s% Y  d
- X5 U  k1 Z( t9 l) i
(((PLL_P >> 1) -1) << 16)
  A! W1 B! Q* v3 x% P7 L其他外设的时钟配置时0 h1 s4 f- n' F, x
  1. /* HCLK = SYSCLK / 1*/
    " _; I. @% ?2 ^5 _. K
  2. RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
    ! j3 C6 a! @, Q  s- B+ Y
  3. /* PCLK2 = HCLK / 2*/
    ( s: W0 ]1 Y( d$ g3 O% ^
  4. RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;' x# s% g( A. ~5 F" V6 p0 o5 _
  5. /* PCLK1 = HCLK / 4*/1 I% x) V4 [1 k- ?6 `
  6. RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
复制代码
% L+ w0 _) E1 W6 ]/ E5 z! K
03、备 注

2 q$ |  [- c! e) [5 Q时钟中断% }8 ]; X: f9 q( S

! M2 R* r. L& F4 T: p8 K: `/ u
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
9 X( Q+ u5 s+ F* c

4 ^; N. L1 p5 u4 r可以配置外部晶振出错时的中断,还有RCC中断,因此我们可以在外部时钟出问题时,切换为内部时钟,不至于整个系统挂掉。具体见ST给的官方代码。. s- p' n  D  G, v5 v: A/ q2 ~

6 N  h# ^* L# a) E7 [3 I, ^ 无源晶振不起振
. N# B! O5 J% O# r( m3 i
6 Z- z6 ~! e- J) h5 X+ D" C9 N没有程序,无源晶振是不起振的,需要配置RCC时钟控制寄存器的HSEON位打开或关闭HSE振荡器。具体可以看之前的文章《晶振原理解析》。
) z5 o1 }+ B2 k" C1 j( u4 p2 ~1 Y# e, I; H+ l
关于APB和PCLK
# k, H8 J9 a7 A
' y9 {0 C# [1 w7 q  O% R
F207是时钟图没有显示PCLK1和PCLK2,应该就是APB1和APB24 u/ A8 q( D+ O2 O5 I4 y! F' }) O# M
5 f3 e* Q) t0 ]& h
应该指的是一个PCLK应该是PeripheralClock的简称,看F105手册
. _  k2 e  R+ J$ C" x, ~# F3 _# ^9 {9 g8 m' R5 B2 c, q( p0 W
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.jpg

" ?2 j  T; f3 z  s: l
- v0 L  t6 ?; N& o3 t
# a+ D) F. {7 v8 y" w' A
7 O: L9 H' O' ]- k* z$ x' k- {, k/ q1 L: _" M

8 t& {) n9 \. k, ]- b
. D, A# L, {' m2 g7 _/ \+ x" X4 h) O' i# o
收藏 评论0 发布时间:2021-12-3 17:00

举报

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