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

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

[复制链接]
STMCU小助手 发布时间:2022-4-19 22:00
01、时钟系统介绍, f( U0 ?6 r( S( Z
( I) J1 s  ^, x
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
8 @; N" {; ~; F2 [  }- a0 d: @& C% H
▲时钟系统专业名词缩写& _2 P8 V! w4 _, K" y, v/ C- `4 J4 `

, y1 v+ S$ O) p) N- I+ Q
/ h6 @- ?: S' _' D* J8 u时钟系统关键组成部分. b# K( @5 _, c
1 X9 v, O1 B7 S
01 内部高速时钟(HSI)
# n8 N) x2 Z9 u% f
# k, I5 }2 E9 l+ k& T7 o4 Q# [1 O
HSI时钟信号可以通过内部16MHZ的RC振荡器产生,可以直接用于系统时钟或者用于PLL输入。
% A/ z1 R+ {7 X% }7 T) O  W$ J0 G- ^: \! y) s3 G& _! D3 j
HSI的RC振荡器的优势是:在最小成本(没有外部器件)情况下提供一个时钟源。它的启动速度要比HSE晶体振荡器更快,但是即使校准频率后,它的精度仍然小于外部晶体振荡器或陶瓷谐振器。" h% ?5 o1 y9 M

$ ^3 G3 f% ]" ]6 y2 x. F6 V02 外部高速时钟(HSE): J( A- M7 I% b! s) d! _+ }, s
$ m- l9 q/ {) ^& l. Z
外部高速时钟信息(HSE)可以通过两个时钟源产生:
$ [3 \9 [2 U+ ^. V
) \' l) k/ i% E: R- H+ [① 外部晶体/陶瓷谐振器- k) v7 T* B3 o; n) j
) a5 c8 [' S9 |; w8 L* w) }0 G
② 外部用户时钟
% I, l% r/ E% m; A1 Y5 w4 S# ~2 }* L9 I* r( Z& x
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png 1 p5 T, j7 t8 o2 M, a9 B2 M# @
+ p4 h( T# P" h) P# [
▲两种时钟源接入示意图
4 z& g; i( U) U0 k
- K/ v8 ?: d4 O/ F3 T; L5 Q1 Q03 主锁相环时钟(PLL)
$ n9 c: E1 D( x0 o

2 `7 X6 i4 L9 q* Q( uSTM32F2xx具有两个PLL/ P1 z9 I! Z) b% k; ?/ U
# `3 ]: T8 L9 g/ l4 U' z
① 主要的PLL通过HSE或HSI提供时钟,并且有两个输出时钟;( E3 j+ C! R( S7 [6 m0 e, K
9 ~; L! B$ D7 [3 o/ w  I( |% _
② 专用的PLL(PLLI2S)被用于产生一个精确的时钟去实现高质量音频效果在I2S接口;
) d0 i1 M: p9 J. L$ F4 }
9 l9 ?  Y6 U. V8 E$ v* l, u aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png ! J' C0 N6 M: N( Q
8 @' W; g7 h' \6 p+ c! q0 A8 Q
HSE/M*N/P得到PLL时钟
7 _" H' v& i! G3 P- A
0 ~$ x5 n2 M$ E! |5 W, Z% t. |6 c关于PLL锁相环说明! j5 v6 m1 Z+ B0 W: e, b; v
1 \% L/ j. W; s
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png ( D) v3 K( a( x/ T

1 Q) O3 m  j- c. q& C: p& x从1处输入,3处输出是1的N倍。, J; z/ k6 l3 P: E8 L! L- c9 C
/ n( h# Y% C7 e* H" [) I" `
3处除以N又作为输入,当1和2的频率一样,就锁定了。(之所以图上是xN,因为从2看向3的)
) y, Y' c: H; M; }
6 K+ k+ z0 ^; Z- t9 d* P04 低速外部时钟(LSE)3 f, E7 U; t/ i6 g; }) ?
6 _5 c9 P9 Q3 m
LSE是一个32.768KHZ低速外部晶振或陶瓷谐振器。/ Y4 r1 v4 g$ c7 r7 P/ F
; k' a0 @8 X  u, @2 A' d2 M
它的优点:提供低速但是高精度时钟给RTC外设,为时钟/日历或其他时间应用。
% r# N: I" }5 ?7 O1 G4 @1 r9 b$ M  s* w3 K5 p/ ]
05低速内部时钟(LSI)
4 k7 p- s3 T0 J; ^- q: {2 r
) [+ m) i3 Q! B7 ALSI RC作为一个低速时钟源,它可以运行在停止和待机模式中给独立看门狗(IWDG)和自动唤醒(AWU)。它的时钟频率在32MHZ左右。
9 O* L. K$ u6 p* k" K; J( `2 h
( B0 v! _7 m& o02、代码分析& T; p- |  b/ A8 S
时钟初始化代码在system_stm32f2xx.c文件中,大部分时候我们不需要修改时钟代码的,各个总线的频率我们可以在文件头看到。
7 E; Z2 |& n% n& t5 n& L
' f# h1 ]" ]2 ?0 _: w5 E$ S; w
  1. =============================================================================6 }( u: X" M; r" D( k9 _: f- D
  2.   *=============================================================================
    $ g$ L, w1 Y5 i& s$ |& e
  3.   *        Supported STM32F2xx device revision    | Rev B and Y4 f# q# L( U0 t2 @8 t
  4.   *-----------------------------------------------------------------------------+ |7 D: v4 z+ D; ^
  5.   *        System Clock source                    | PLL (HSE); |0 f( ?) b2 G: C: A
  6.   *-----------------------------------------------------------------------------
    : W* s, O4 ^! S2 s& p7 j
  7.   *        SYSCLK(Hz)                             | 120000000
    . k1 ^* b; _: B7 c* O! A, G1 E* p+ z; r% K
  8.   *-----------------------------------------------------------------------------
    ; d# F- ]- `+ u+ G2 e5 F0 M
  9.   *        HCLK(Hz)                               | 120000000  D, g) _6 M- w7 D7 g
  10.   *-----------------------------------------------------------------------------
    - g9 g7 s0 C6 C5 @1 \1 S, Y
  11.   *        AHB Prescaler                          | 1+ ~' u/ V0 J" \
  12.   *-----------------------------------------------------------------------------1 ^2 P  w1 C' W9 H
  13.   *        APB1 Prescaler                         | 4) i# r2 X# o- c  H) ^: ~
  14.   *-----------------------------------------------------------------------------$ C; z( p( A- v# Q, v7 p+ z
  15.   *        APB2 Prescaler                         | 2  w$ b7 c" f- e. x9 w# Z2 ]
  16.   *-----------------------------------------------------------------------------# w$ F( c" P; F0 @$ R0 _
  17.   *        HSE Frequency(Hz)                      | 25000000
    6 |: F9 r$ ~6 g* s7 r+ |
  18.   *-----------------------------------------------------------------------------7 n# v) ?3 m9 b" X2 K+ h
  19.   *        PLL_M                                  | 256 H0 k# ?* Y5 t( Z
  20.   *-----------------------------------------------------------------------------9 l2 w7 m8 t- R8 p' c
  21.   *        PLL_N                                  | 240
    $ [1 n# q3 y- g1 y# w
  22.   *-----------------------------------------------------------------------------
    ' \" x. H5 J) q8 G3 W, {% i
  23.   *        PLL_P                                  | 2
    ( |* i9 U8 ?" B4 h- y
  24.   *-----------------------------------------------------------------------------
    ; C  F7 Q. D  |6 Z. O
  25.   *        PLL_Q                                  | 5
    7 w- P' j. z7 [. t0 S# l
  26.   *-----------------------------------------------------------------------------
    ) n' p* K4 `7 Y# @
  27.   *        PLLI2S_N                               | NA" J. }* m. D) g
  28.   *-----------------------------------------------------------------------------% T: V* _# {9 [  C
  29.   *        PLLI2S_R                               | NA
    ( Q. z7 a+ n' p8 }' F3 ?& H
  30.   *-----------------------------------------------------------------------------5 Z7 T& O6 q5 Y9 D- [! _7 V
  31.   *        I2S input clock                        | NA' T% F% U, }0 q9 p* h+ P
  32.   *-----------------------------------------------------------------------------: C% K+ R7 j0 J5 {: [- _
  33.   *        VDD(V)                                 | 3.34 J3 S- x5 z. N5 e! C. H
  34.   *-----------------------------------------------------------------------------% M/ u0 l5 p9 F3 J3 \+ `4 [
  35.   *        Flash Latency(WS)                      | 30 j8 `: d! q+ ?$ @; u
  36.   *-----------------------------------------------------------------------------* b) y& r4 R  B, R8 k( N
  37.   *        Prefetch Buffer                        | ON
    5 v; P6 N" X2 Z  S
  38.   *-----------------------------------------------------------------------------. C  ~! x' M3 i! W3 H7 p0 X
  39.   *        Instruction cache                      | ON) Z4 o$ W3 w7 h. O
  40.   *-----------------------------------------------------------------------------/ \$ g0 ?1 x8 w$ J# M$ i- k
  41.   *        Data cache                             | ON
    9 X  s: C4 |8 @: N# N
  42.   *-----------------------------------------------------------------------------
    ! E* Z- d5 t% T' }9 J* {
  43.   *        Require 48MHz for USB OTG FS,          | Enabled; K3 o' x, A6 `3 W- ?8 i( C- z+ C
  44.   *        SDIO and RNG clock                     |
    + V# U9 @" G; Q: Z2 K' R0 {/ x! [
  45.   *-----------------------------------------------------------------------------
    % F) g" G& B0 j5 C! Z" f: y' n
  46.   *=============================================================================
    & N: C, k) B4 C9 R- B  v+ Z4 W3 i
  47.   ******************************************************************************' m9 N* l/ o2 G# |" G5 j: _
复制代码
( }% _+ c& r, M" B/ c" g
在文件开始定义的有系统时钟频率的全局变量SystemCoreClock,其他地方需要时钟频率,可以直接使用该变量。& F, f. e. I* x# p, S6 x: m8 F
  1. uint32_t SystemCoreClock = 120000000;
复制代码
5 ?1 l6 o7 m: e
时钟配置从SystemInit函数执行,调用SystemInit的在汇编文件中startup_stm32f2xx.s(Keil编译环境)。
' q7 J/ I* v3 ~. E1 Z! z% W4 F9 n" N5 P( p4 [3 ~$ n
  1. IMPORT  __main
    ! ]; `6 W0 R7 M, B4 ]
  2.     LDR     R0, =SystemInit
    6 J# K- S4 {9 w6 S9 l! E
  3.     BLX     R0
    . L/ x8 M* W$ S+ S
  4.     LDR     R0, =__main
    2 c( s/ o8 [6 ?$ [+ C0 J  u
  5.     BX      R0) p5 u7 R9 ^5 L$ ^* z" i2 }
  6.     ENDP
复制代码
3 d' K' l) L: }2 G# t/ I! }' d( k2 Z
在这里说明一下文档版本的问题:
% O% @- Y3 t# n( t
) k- L7 s, u; I9 o' v aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
6 V( I1 o1 L9 O0 A9 f
. ^9 {- d- Q5 ?# O▲STM32F20X_User_manual的V7版和V8版对比图) U1 o3 P' R5 U& m

' c+ M& J5 D' [上述两图的区别是系统最大时钟从120MHZ变成了168MHZ,我的理解是同样是STM32F20X,ST由于技术进步或其他,使得新版STM32F207芯片超频支持168MHZ。
/ P; U4 ^) f' }& z  N% O
- t4 W3 I* B- [- G在线预览地址:4 C6 a( A9 i8 `

2 D  b/ L1 P% _$ W# ~+ k下面我们主要分析SystemCoreClock的120M时钟怎么从一个外部25MHZ的HSE得到的。
- m# `  G( b. s( `8 P9 X5 e3 R0 A+ L, d7 S
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png 3 ^" u' a$ ^. ?/ b+ L
! @" ?6 Y& F! J; y
我们要从25MHZ的外部时钟得到120M的系统时钟,需要上图中标注的重要4点:
0 J6 z( y$ Q+ C
+ {3 \: l' G; P9 Y. {/ }6 v1、使能HSE
( E6 W! w& ~+ w  T& Q; c3 \7 z! |. I! {6 v' `/ Z
2、选择HSE作为主PLL的输入时钟9 n, Z+ d4 V( d
7 G$ v. L' @8 m* ~/ c0 B
3、主PLL倍频后得到120MHZ时钟
2 X0 n" l! T& F" G5 u# j
4 A( @7 z" N: k' ~: `! d6 l4、系统时钟选择主PLL时钟输出作为系统时钟
$ o. u$ O6 Z6 q* P* g
! P8 w% r% v- j$ D我们找到对应的代码
3 |" p! M" S0 A) M8 W
+ u8 V$ p. Z7 Q; F4 C6 `* ]  1、使能HSE( B8 V7 Z5 ?. }" \: ]3 d5 X# t: y9 B
* @  \  U& V$ ]0 d1 E/ N
  1. /* Enable HSE */
    " ?  m8 H6 w* g" c6 h
  2. RCC->CR |= ((uint32_t)RCC_CR_HSEON);
复制代码

4 ~9 M8 ~; U/ H6 ~- w1 |# z在RCC_CR寄存器(RCCclock control register RCC时钟控制器)中,有打开HSE的控制位
7 F/ z# g5 z- R. x% a& r aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png : q9 X& J' N$ d
+ E  k) r1 N; r# r
2、选择HSE作为主PLL的输入时钟4 ^* U- F5 @4 B: u
5 l  @7 Y  C. z! r1 }8 y
  1. /* Configure the main PLL */
    & f, f3 S5 u' }3 p( }( o
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
    & J( r8 W$ o. I$ g3 B+ q" _
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码
# ~0 ?$ V! p1 x1 X. \0 P  r
RCC_PLLCFGR_PLLSRC_HSE就是配置HSE作为主PLL的输入时钟
1 ]$ @* E0 e! ^7 Y/ Q: t# r: p8 O* A9 n2 E1 @
  3、主PLL倍频后得到120MHZ时钟
0 C2 N0 ?+ R& ?7 d, t9 D( @$ ~5 Q- r5 L6 r* N$ T  d+ `
  1. /* Configure the main PLL */
    ! }3 R) f; K& k1 l3 |- v8 j$ i  R
  2. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |5 _( j! z( H/ T/ P
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码
* K: q+ D: r: C; r1 z
4、配置主PLL作为系统时钟的输入时钟
  1. /* Select the main PLL as system clock source */
    # W5 A" G" y# V' D" q
  2. RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));( F" `0 V) K4 ^2 ]. G8 A! v0 R( e
  3. RCC->CFGR |= RCC_CFGR_SW_PL
复制代码

$ U+ e- l7 V& H7 L8 Y# U* q5 j0 ~对于主PLL的配置寄存器,在RCC_PLLCFGR寄存器中有说明/ K' R0 f$ }0 E' w  [+ q

; G* w. i" z9 c! t$ P1 F aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png 1 F, j& C3 m- S. j

' N& z( J: p4 S% Z" T整理后得知f(out)=f(in)* N / M / P/ G0 T* [$ h: C3 u& Y) {% ]7 h' V
3 x6 X9 t& v5 Y) N: ]1 `
  1. /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
    $ V, ~2 L% z' Q/ d6 n, Q2 `6 q
  2. #define PLL_M      253 U) A" w( c- A
  3. #define PLL_N      2400 b6 }" p+ K4 N+ G3 Y# n' m" d8 P& N
  4. /* SYSCLK = PLL_VCO / PLL_P */
    2 [$ D1 K6 R& I6 o2 e" _
  5. #define PLL_P      2
复制代码
+ ~# Q9 X( f! X2 q6 f
这样就获得了120M时钟
, U$ T) X% }' G: s$ }' m; m2 h9 s% X4 r3 l- v; q
注意:/ e' v! V9 x/ L7 F" z3 }- X

' I- b; `: S4 t! X aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png ! O0 g+ Q3 |0 `% c0 M: J
# l' p: Q$ P# T" }' U8 |
PLL_M大于等于2且小于等于63* o6 e6 r2 B6 X4 ~
( u4 e9 o3 t: q* v% l* x# H& w
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png 9 Z7 ?6 f$ ]9 ^6 f+ G9 K- r. r- K
$ U. J6 x; J7 |' N  u5 M
PLL_N大于等于64且小于等于432
: w' ~4 G2 u4 r/ W" @6 i* [$ R- b6 S+ K9 P$ b% {
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png . B  G3 C8 r. t7 O
; E- q; ]$ }6 _
PLL_P只能是2、4、6、或8
/ E6 k: G6 S/ T3 @2 y$ d) T& [1 I5 D" a2 N5 a
但2对应0,4对应1,6对应2,8对应3。/ P7 t; E: N) ^9 [5 J# P
/ c9 n& V/ ]/ J6 a# O8 U
ST并没有使用if或case语句判断,因为对应的数据除以2减去1就是寄存器这两位的值,所以可以按照下面这样写,这种写法值得我们学习。  ^+ x; h" C, g2 t
& I+ c/ M% S% e! @
  1. (((PLL_P >> 1) -1) << 16)
复制代码
5 d  m: a8 A8 U/ R! O
其他外设的时钟配置时9 U$ n  p) o. L; d
! E6 Q- E. R$ c9 e7 \& b9 }* p
  1. /* HCLK = SYSCLK / 1*/) R1 ]; A  `% C$ ~/ P- H- v" i1 Q
  2. RCC->CFGR |= RCC_CFGR_HPRE_DIV1;' r- i; ~2 E/ Z
  3. /* PCLK2 = HCLK / 2*// r- O4 v- t. j; w$ K
  4. RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;; A( A6 }0 i& }. D. F/ H' I( i
  5. /* PCLK1 = HCLK / 4*/
    6 D! o) I# o, M6 Q& S' g& N) w. G
  6. RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
复制代码
7 ?6 [+ T: {4 T& H
03、备 注   E2 q; l1 z) W, u1 }" ?1 F* o4 y
时钟中断
1 J1 ~! e6 i; |' K1 v7 x* t
7 h: i) N3 j' h
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
2 f7 \% j# Y1 W, M5 v# g( p" d7 X8 F6 g
可以配置外部晶振出错时的中断,还有RCC中断,因此我们可以在外部时钟出问题时,切换为内部时钟,不至于整个系统挂掉。具体见ST给的官方代码。5 @1 ~* C- T! D  H8 \
0 b7 p0 f" [9 \& I0 L( R
无源晶振不起振. P' i: D7 k3 @4 ^* b5 E
! C  }* i8 g0 X6 M; w- N
没有程序,无源晶振是不起振的,需要配置RCC时钟控制寄存器的HSEON位打开或关闭HSE振荡器。具体可以看之前的文章《晶振原理解析》。
6 U/ X# z. ^6 C& @. f
. v, @  {! q. \3 W' m; l 关于APB和PCLK  v7 J# t0 Y4 r% ~! M( r

. _$ t4 l( M; Y5 Z& i2 y6 K8 u: FF207是时钟图没有显示PCLK1和PCLK2,应该就是APB1和APB2  e4 l7 N8 V7 e' Y% C
8 o% ?7 o, e+ F0 x% a6 W
应该指的是一个PCLK应该是PeripheralClock的简称,看F105手册
8 r& C- u; t# y, t- p2 Z0 b" v* f5 O! C6 t4 L& n+ `
aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X2pwZy8wUmc4RGRwQWliZlVxc2pZQ3lEVzVKQUZpY3NG.png
! J* n" u, j# [, I+ a. |  X4 T
, S) r$ U& X5 I3 K. h, S% y2 V8 l0 D& j4 v# u
4 K8 ?7 v4 M9 E
赞 收藏 评论0 发布时间:2022-4-19 22:00

举报

0个回答

所属标签

相似技术帖

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版