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

【经验分享】STM32F4时钟系统

[复制链接]
STMCU小助手 发布时间:2022-6-10 20:08
01. STM32F4时钟系统概述
9 h7 C! a* Q1 E2 }: a0 M" z, M时钟系统是 CPU 的脉搏,就像人的心跳一样。所以时钟系统的重要性就不言而喻了。 STM32F4 的时钟系统比较复杂,不像简单的 51 单片机一个系统时钟就可以解决一切。于是有人要问,采用一个系统时钟不是很简单吗?为什么 STM32 要有多个时钟源呢? 因为首先 STM32 本身非常复杂,外设非常的多,但是并不是所有外设都需要系统时钟这么高的频率,比如看门狗以及 RTC 只需要几十 k 的时钟即可。同一个电路,时钟越快功耗越大,同时抗电磁干扰能力也会越弱,所以对于较为复杂的 MCU 一般都是采取多时钟源的方法来解决这些问题。$ N7 c4 q' g( B8 A. @

' g1 A) N. ^7 X/ i" H02. STM32F4时钟系统图
# k0 |7 b# {6 P4 K  I; E
1 W  I# h3 W  n: ^# Y. [1 m0 x7 v4 W
54RK2N3M}XS88ZREGCB7RB6.png
* ~* X& S  f5 I" q, n# @1 d1 h% v  n* o5 l7 L$ z  m3 l
在 STM32F4 中,有 5 个最重要的时钟源,为 HSI、HSE、LSI、LSE、PLL。其中 PLL 实际是分为两个时钟源,分别为主 PLL 和专用 PLL。从时钟频率来分可以分为高速时钟源和低速时钟源,在这 5 个中 HSI,HSE 以及 PLL 是高速时钟,LSI 和 LSE 是低速时钟。从来源可分为外部时钟源和内部时钟源,外部时钟源就是从外部通过接晶振的方式获取时钟源,其中 HSE 和LSE 是外部时钟源,其他的是内部时钟源。下面我们看看 STM32F4 的这 5 个时钟源,我们讲解顺序是按图中红圈标示的顺序:* o' p" ?8 |! p% h1 f

& M' F; `5 N( k, X①、LSI 是低速内部时钟,RC 振荡器,频率为 32kHz 左右。供独立看门狗和自动唤醒单元使用。
) x# `; G* w; }% m! c4 A, {1 t②、LSE 是低速外部时钟,接频率为 32.768kHz 的石英晶体。这个主要是 RTC 的时钟源。
* r& B* c# V% F  ?③、HSE 是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为 4MHz~26MHz。我们的开发板接的是 8M 的晶振。HSE 也可以直接做为系统时钟或者 PLL 输入。: q% g! l  |# M& }3 i5 m4 m
④、HSI 是高速内部时钟,RC 振荡器,频率为 16MHz。可以直接作为系统时钟或者用作 PLL输入。8 n( b  v: O/ M, @* n% @6 t
$ S+ \0 |7 w3 m' }( p8 `4 I
⑤、PLL 为锁相环倍频输出。STM32F4 有两个 PLL:
4 y- V; F! {. T$ p3 J1) 主 PLL(PLL)由 HSE 或者 HSI 提供时钟信号,并具有两个不同的输出时钟。
! o6 g* z7 F* u8 r第一个输出 PLLP 用于生成高速的系统时钟(最高 168MHz)
/ j4 q  e- J& H; W7 _* X第二个输出 PLLQ 用于生成 USB OTG FS 的时钟(48MHz),随机数发生器的时钟和 SDIO时钟。$ f" W, W7 E# T$ `
2)专用 PLL(PLLI2S)用于生成精确时钟,从而在 I2S 接口实现高品质音频性能。6 C# Q$ N4 v( U; s- b# c/ H4 V3 `

5 C" z- Z' x# ?0 AA. 这里是看门狗时钟输入。从图中可以看出,看门狗时钟源只能是低速的 LSI 时钟。
8 t8 v7 ~, }8 Y" D# V' W% M( v1 k
$ `8 b  n+ {. oB. 这里是 RTC 时钟源,从图上可以看出,RTC 的时钟源可以选择 LSI,LSE,以及HSE 分频后的时钟,HSE 分频系数为 2~31。  @. h7 U9 W9 ^6 ?* K6 L. `$ B
/ d; [& Y4 \: `0 {, H8 k
C. 这里是 STM32F4 输出时钟 MCO1 和 MCO2。MCO1 是向芯片的 PA8 引脚输出时钟。它有四个时钟来源分别为:HSI,LSE,HSE 和 PLL 时钟。MCO2 是向芯片的PC9 输出时钟,它同样有四个时钟来源分别为:HSE,PLL,SYSCLK 以及 PLLI2S时钟。MCO 输出时钟频率最大不超过 100MHz。
  a$ m5 w' ]3 F, E7 D8 V) I" W, D- I
D. 这里是系统时钟。从图 4.3.1 可以看出,SYSCLK 系统时钟来源有三个方面:HSI,HSE 和 PLL。在我们实际应用中,因为对时钟速度要求都比较高我们才会选用 STM32F4 这种级别的处理器,所以一般情况下,都是采用 PLL 作为 SYSCLK时钟源。根据前面的计算公式,大家就可以算出你的系统的 SYSCLK 是多少。# b4 i" A. O& _- g+ j% I

/ R2 Z  @& Y) e! t4 g- gE. 这里我们指的是以太网 PTP 时钟,AHB 时钟,APB2 高速时钟,APB1 低速时钟。这些时钟都是来源于 SYSCLK 系统时钟。其中以太网 PTP 时钟是使用系统时钟。AHB,APB2 和 APB1 时钟是经过 SYSCLK 时钟分频得来。这里大家记住,AHB最大时钟为168MHz, APB2高速时钟最大频率为84MHz,而APB1低速时钟最大频率为 42MHz。
3 I: A9 z4 a6 y- ], ]% n: u$ j: @5 `& O
F. 这里是指 I2S 时钟源。从图 4.3.1 可以看出,I2S 的时钟源来源于 PLLI2S 或者映射到 I2S_CKIN 引脚的外部时钟。I2S 出于音质的考虑,对时钟精度要求很高。探索者 STM32F4 开发板使用的是内部 PLLI2SCLK。6 n& K3 b( p0 l' {9 t3 }
3 f2 Z" \* N) {" x
G. 这是 STM32F4 内部以太网 MAC 时钟的来源。对于 MII 接口来说,必须向外部PHY 芯片提供 25Mhz 的时钟,这个时钟,可以由 PHY 芯片外接晶振,或者使用STM32F4 的 MCO 输出来提供。然后,PHY 芯片再给 STM32F4 提供ETH_MII_TX_CLK 和 ETH_MII_RX_CLK 时钟。对于 RMII 接口来说,外部必须提供 50Mhz 的时钟驱动 PHY 和 STM32F4 的 ETH_RMII_REF_CLK,这个 50Mhz时钟可以来自 PHY、有源晶振或者 STM32F4 的 MCO。我们的开发板使用的是RMII 接 口 , 使 用 PHY 芯 片 提 供 50Mhz 时 钟 驱 动 STM32F4 的ETH_RMII_REF_CLK。
) ^' V/ k5 \* h# }
8 J, b5 M" Y2 B& x4 ^H. 这里是指外部 PHY 提供的 USB OTG HS(60MHZ)时钟。
2 }1 o, O2 R6 y9 O  y& B, w" U8 R* B3 w  I7 o* T
03. STM32F4时钟初始化配置
+ `+ |8 F$ e+ j" F- d# P; CSTM32F4 时钟系统初始化是在 system_stm32f4xx.c 中的 SystemInit()函数中完成的。对于系统时钟关键寄存器设置主要是在 SystemInit 函数中调用 SetSysClock()函数来设置的。我们可以先看看 SystemInit ()函数体。
, A) o( O" n9 d0 A6 r% @4 q# o% d& e* r* u6 o
  1. /**! o. b: b" `  F  ]# U
  2.   * @brief  Setup the microcontroller system
      ?8 k6 I) H* e5 ?: _6 I6 u
  3.   *         Initialize the Embedded Flash Interface, the PLL and update the
    - L( c- X" l, i2 p" k
  4.   *         SystemFrequency variable." }9 b6 {' q- p) O- w' u7 r
  5.   * @param  None/ @0 O* \- ~  p4 Z: V' i3 m
  6.   * @retval None/ s( d/ W0 m  s' L! L1 P) n/ g
  7.   */* T& G7 ~9 E" r5 |9 K
  8. void SystemInit(void)( \6 p6 N% j) B4 [4 l2 ~/ S) F
  9. {
    $ m- B/ w2 W. ?% u
  10.   /* FPU settings ------------------------------------------------------------*/! `' U& G. ]: }" X. k0 Q/ B, L- ~
  11.   #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
    ) i5 w6 y/ ^, C1 {4 ]  A# K
  12.     SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
    # h3 z) q3 ~# q2 Y. R- N6 e7 O; E
  13.   #endif5 P7 Z) ]( \+ S3 ]
  14.   /* Reset the RCC clock configuration to the default reset state ------------*/
    0 O" R9 X) m; u  o
  15.   /* Set HSION bit */
    0 S# f: {) _% n# U) }$ w
  16.   RCC->CR |= (uint32_t)0x00000001;
    0 w( [  a8 A$ O& @
  17. * S8 r: i( y7 W% U7 I. h+ T) w
  18.   /* Reset CFGR register */) S$ N( f2 U( M# o; p+ X: n  M
  19.   RCC->CFGR = 0x00000000;
    6 j/ i. f: `8 v/ q

  20. % P9 O8 I* }- {- y, n
  21.   /* Reset HSEON, CSSON and PLLON bits */
    / O: ], T3 x3 i' C8 s1 {# R
  22.   RCC->CR &= (uint32_t)0xFEF6FFFF;
    & o# B! ~/ G! j% P& x' k

  23. $ o- z6 ~8 |& m: K; \" h& ~6 _
  24.   /* Reset PLLCFGR register */
    3 D- z4 a, B, w( l( n
  25.   RCC->PLLCFGR = 0x24003010;
    + m$ n, v# `, U/ |; V
  26. ! Y& G& S3 }# {4 P" n; q0 f# H
  27.   /* Reset HSEBYP bit */
    ' v5 J" w4 o# W& g* _! }
  28.   RCC->CR &= (uint32_t)0xFFFBFFFF;6 ^- L/ I0 G( ?, L. B0 B' [1 m

  29. 8 r6 u0 L5 y- u, u. a8 l, d, i
  30.   /* Disable all interrupts */
    " E" Q/ j, y$ Q
  31.   RCC->CIR = 0x00000000;
    ( L, \) M/ X7 m( U- e
  32. 1 \2 T- ~- H& Y0 S& u1 [  _8 Y
  33. #if defined(DATA_IN_ExtSRAM) || defined(DATA_IN_ExtSDRAM)
    ! Z( R! V' a% c( P
  34.   SystemInit_ExtMemCtl();
    . T. o! G& n  ?4 G) H
  35. #endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
    $ B8 R# ]) M& ?
  36. / {, h% x9 X% h$ q% l" m! e  ~
  37.   /* Configure the System clock source, PLL Multiplier and Divider factors,
    4 }! b9 K  t: K4 s/ j7 }
  38.      AHB/APBx prescalers and Flash settings ----------------------------------*/  Z. m8 a9 y* f& p9 @. I
  39.   SetSysClock();
    2 c2 u  ^, |, m
  40. ) n+ O  M- B0 Z* d/ s
  41.   /* Configure the Vector Table location add offset address ------------------*/5 I) J% `: b5 k! v# I% X5 |) K
  42. #ifdef VECT_TAB_SRAM
    ' M' h9 [) ^) d$ `
  43.   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */" t0 G9 _  i! A% q
  44. #else4 m- V, D$ F+ B' n" t. R3 W
  45.   SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */4 \1 a4 T& A# R! N6 W
  46. #endif
    2 ~7 f" Q0 e9 E1 `/ p$ Q1 P* {( O
  47. }
复制代码
1 X, F6 J" K" ]+ }
在设置完相关寄存器后,接下来 SystemInit 函数内部会调用 SetSysClock 函数。
3 k2 P1 s7 V3 Z" U- H6 S) o8 u" p7 r3 x5 J: _
  1. /**0 S- k: ~$ q- f6 x# i  r
  2.   * @brief  Configures the System clock source, PLL Multiplier and Divider factors,
    & Q) J6 Z: n$ f& Q7 S; X
  3.   *         AHB/APBx prescalers and Flash settings3 m3 t9 I6 C8 \; N, ~
  4.   * @Note   This function should be called only once the RCC clock configuration  , }/ m0 N3 Z5 P: {2 t+ d  s+ L
  5.   *         is reset to the default reset state (done in SystemInit() function).   
    9 t" h4 T; |$ w; B
  6.   * @param  None
    & f. F8 t& R, K2 J
  7.   * @retval None
    5 R7 a' {6 K0 {, o; M; G+ \( T- m
  8.   */
    ' q( W6 u+ v( a! l" a; _
  9. static void SetSysClock(void)
    4 e9 d# v$ c; T  G9 w1 G5 g
  10. {# ?7 q* {& ?4 S/ p! b+ j
  11. #if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F401xx) || defined(STM32F412xG) || defined(STM32F413_423xx) || defined(STM32F446xx)|| defined(STM32F469_479xx)
    ; ]6 A: ?( K! ]! _. d6 t
  12. /******************************************************************************/) D# m* ]+ h# P6 S3 t' Z
  13. /*            PLL (clocked by HSE) used as System clock source                */
    + V5 }, R: w0 f+ z9 c# W  @0 I+ Y
  14. /******************************************************************************/
    / ]5 @/ M% N8 Q; Y" g$ D0 f5 M
  15.   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
    : }, |' O2 u8 s1 B; X. ^
  16. - n" z; a- h1 p& h, K4 _
  17.   /* Enable HSE */ //HSE时钟使能
    5 x- y# z5 {2 I. x/ P# e) l
  18.   RCC->CR |= ((uint32_t)RCC_CR_HSEON);0 h/ @$ @4 w- g6 ]( M$ s# u
  19.   //等待HSE时钟稳定
    # @5 S2 h% I2 G
  20.   /* Wait till HSE is ready and if Time out is reached exit */
    & i0 }1 N" C) i0 v" e/ |( [
  21.   do
    % t3 L' l8 v+ @0 F- p
  22.   {
      \/ {* i# \- Z1 F3 m7 d0 O
  23.     HSEStatus = RCC->CR & RCC_CR_HSERDY;, S0 ]/ }+ C# Z
  24.     StartUpCounter++;- Y' v% l# l3 u( o
  25.   } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
    : P* f( O, D# Q0 B1 J: a; D

  26. 3 C  P: _, Z* ?' ]% Q' `3 ~. _
  27.   if ((RCC->CR & RCC_CR_HSERDY) != RESET)" c8 u1 z" a: x$ r
  28.   {
    % V  u0 C! \8 \8 J
  29.     HSEStatus = (uint32_t)0x01;
    . m% }% v& y/ m! t7 s! m" d
  30.   }
    ) M* h; T2 h5 ]2 I9 i
  31.   else- @. t  l9 F4 F9 u5 s
  32.   {
    & s  Y2 z! m8 ~/ }% j  w
  33.     HSEStatus = (uint32_t)0x00;
    2 r5 X. u; V7 F& B4 I# m- P+ d
  34.   }& {! \3 L& ~* t1 L1 o. V5 J" ]
  35. + f. {! `- @" T
  36.   if (HSEStatus == (uint32_t)0x01), U! Z( ^; }) k  H+ n- U  b
  37.   {+ i' p3 V' q& v: ]9 p/ K! N
  38.     /* Select regulator voltage output Scale 1 mode */
    5 W% o2 f. A$ y2 c; D( L$ ~
  39.     RCC->APB1ENR |= RCC_APB1ENR_PWREN;+ D2 ]' P. `# k, {- v$ H1 ?
  40.     PWR->CR |= PWR_CR_VOS;& G4 s6 Z% u* Q4 F
  41.         //AHB不分频  [5 [2 Z" I8 x% D( Y. G3 i2 q; f; r
  42.     /* HCLK = SYSCLK / 1*/
    ( G0 C( Y5 s9 t, r' [% e1 p6 m
  43.     RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
    ; @8 n* q+ k1 X9 w

  44. : O4 I( N* T$ j- [
  45. #if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) ||  defined(STM32F412xG) || defined(STM32F446xx) || defined(STM32F469_479xx)    % f& L0 Z# g$ I# |3 F7 |$ `( F
  46.     /* PCLK2 = HCLK / 2*/ //高速APB二分频
    & L, @/ `3 ~/ ^! V) j$ N
  47.     RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
    - U; V* W, [( w% I

  48. ) V  B$ [  I' |  ^
  49.     /* PCLK1 = HCLK / 4*/ //低速APB4分频7 A+ s/ u* M/ G: Y0 t( ]5 M
  50.     RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
    9 F+ j" x4 j7 p2 y  Q  F
  51. #endif /* STM32F40_41xxx || STM32F427_437x || STM32F429_439xx  || STM32F412xG || STM32F446xx || STM32F469_479xx */
    0 W6 ~% K" X; J( `$ |+ R: d
  52. 2 g% `% w& s' y2 T% c5 t0 m7 n
  53. #if defined(STM32F401xx) || defined(STM32F413_423xx)* {5 r" H+ F. ?. e& @8 I3 B, T
  54.     /* PCLK2 = HCLK / 1*/
    : c) l- {! C( h8 V: ]" m
  55.     RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;
    ) x4 l: v2 ^- E5 Q/ I0 ?
  56. ; Q$ [. l: G9 ^0 k
  57.     /* PCLK1 = HCLK / 2*/+ s7 `7 `. H5 a. G1 J0 @# y
  58.     RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;" E# T0 m  M4 e  e' q( I
  59. #endif /* STM32F401xx || STM32F413_423xx */9 ]5 X  J3 h) N4 }, E

  60. ! I# I& [% P+ b$ ?/ Y" P( m+ R/ _
  61. #if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F401xx) || defined(STM32F469_479xx)    ( L/ R+ U6 M& K: U9 _, P" e
  62.     /* Configure the main PLL */) @/ Z9 h. l% n4 e
  63.     RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |1 F$ g1 B' p0 Q: v! q8 f6 |% y( ~* Z: a
  64.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
    / v. u1 q  P5 W; g: W
  65. #endif /* STM32F40_41xxx || STM32F401xx || STM32F427_437x || STM32F429_439xx || STM32F469_479xx */6 O4 g" V0 w9 l4 t
  66. " v5 `# |8 p& L% [* M" @0 J) K
  67. #if  defined(STM32F412xG) || defined(STM32F413_423xx) || defined(STM32F446xx)
    + Y$ M+ K7 C/ i3 B! w: i) K
  68.     /* Configure the main PLL */* M9 C% G: h" z, @
  69.     RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |, o( v$ W7 W. m
  70.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24) | (PLL_R << 28);, O5 r2 Z$ _' F/ m+ H; m
  71. #endif /* STM32F412xG || STM32F413_423xx || STM32F446xx */   
    * {& j: z7 R( [/ t' k! Z/ `7 o! {

  72. ' f  e) ]5 V3 ]5 U6 s- c
  73.     /* Enable the main PLL */
    - R, z) ]$ F. T# q  R) F  g  H; V
  74.     RCC->CR |= RCC_CR_PLLON;
      u, ^% I# y0 M& C( @
  75. + d/ J8 x) Y! t1 q
  76.     /* Wait till the main PLL is ready */
    8 S3 Y8 O6 w- o2 C
  77.     while((RCC->CR & RCC_CR_PLLRDY) == 0)
    $ [# c% J5 j5 P% L# C9 T% d) Q
  78.     {6 j$ k8 \6 s6 ]$ C
  79.     }
    ( X$ ?9 f/ W+ Y4 G2 s: W, E# `! t4 `

  80. ) B5 X+ n" m& v8 Y8 ^1 B
  81. #if defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F446xx) || defined(STM32F469_479xx)% W* W7 C9 ~& L5 o2 z3 r; Z
  82.     /* Enable the Over-drive to extend the clock frequency to 180 Mhz */
    " e+ E9 r: f8 l" a9 \5 ^" o) G  `
  83.     PWR->CR |= PWR_CR_ODEN;2 i4 t/ V  _1 B3 P
  84.     while((PWR->CSR & PWR_CSR_ODRDY) == 0)
    - m" W/ f" n, O; V/ z$ ^
  85.     {( D# h1 O: b4 Q- d, r8 S2 w
  86.     }
    7 I6 w0 i5 S0 E3 D/ w5 j' t
  87.     PWR->CR |= PWR_CR_ODSWEN;& M4 X; V# ^1 G
  88.     while((PWR->CSR & PWR_CSR_ODSWRDY) == 0)5 h9 V3 x% G3 G' i: }
  89.     {
    5 C+ G2 v8 G) o$ L- y: h. K3 t
  90.     }      6 E7 y3 S4 S" ~6 s; E5 k5 l9 z
  91.     /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
    ; N# T% {- j6 N, b" v
  92.     FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
    $ Y, {$ x' t1 H2 n3 ]
  93. #endif /* STM32F427_437x || STM32F429_439xx || STM32F446xx || STM32F469_479xx */
    , y, q2 r- o, Q

  94. 2 L' [, {' n3 ?& N1 b/ i
  95. #if defined(STM32F40_41xxx)  || defined(STM32F412xG)  * t" I( j6 {2 A/ W6 j: V
  96.     /* Configure Flash prefetch, Instruction cache, Data cache and wait state */9 ?5 a9 a! Q4 }
  97.     FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;6 Y  b. ~2 y- W
  98. #endif /* STM32F40_41xxx  || STM32F412xG */
    % |5 L, q3 N4 ^7 }

  99. - k- @' X3 o; \) S
  100. #if defined(STM32F413_423xx)  , c4 v4 r+ `% ^$ @+ H( N6 z
  101.     /* Configure Flash prefetch, Instruction cache, Data cache and wait state */+ u" d* _' N6 M9 {5 ?! ~
  102.     FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_3WS;
    1 [! O& x# E7 |4 Q4 e
  103. #endif /* STM32F413_423xx */8 t; J: Q1 X; L3 F- R3 o

  104. 1 b& e3 [- u( I4 N
  105. #if defined(STM32F401xx)
    $ L* a8 s5 T! z* |$ ]% e  I5 S
  106.     /* Configure Flash prefetch, Instruction cache, Data cache and wait state */$ a, p3 Y9 o: J$ L$ f
  107.     FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS;2 e+ X1 z: X8 X; s# Q! Q! k) _
  108. #endif /* STM32F401xx */
    $ i) c8 g% G. d. l$ |5 R$ y- Z8 s- V* D
  109. 7 b- r4 x* \$ G0 _% d- X/ P* z
  110.     /* Select the main PLL as system clock source */6 ~% J7 o1 V3 u' S5 c
  111.     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));  M0 {- u; P) ]# `6 l3 l
  112.     RCC->CFGR |= RCC_CFGR_SW_PLL;
    ; l6 k9 @5 A3 |% E
  113. 2 k3 S1 g7 }1 x8 l1 h4 v
  114.     /* Wait till the main PLL is used as system clock source */
    8 ?) b) [. C) g5 H% a) \- e6 P8 M% s
  115.     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
    / k3 U) j' g5 x& E% i/ }8 g
  116.     {$ l. e+ r0 G! o3 ^. J; c/ {7 B
  117.     }- }, {) _. q  c- N
  118.   }
    ! [* t& U- u) ~0 t) m; w. E
  119.   else6 z/ x; v+ K/ F* a) K' q* p" r
  120.   { /* If HSE fails to start-up, the application will have wrong clock
    8 n; v1 o! Q0 G) U
  121.          configuration. User can add here some code to deal with this error */
    1 m8 {  {- }/ C' `: V9 @
  122.   }# A: I8 @! s1 Q$ h0 U" l" j( |0 H
  123. #elif defined(STM32F410xx) || defined(STM32F411xE)" p; k$ |, \) B6 G+ t
  124. #if defined(USE_HSE_BYPASS)
    - u( N1 {& J. ^3 [7 T# x  @
  125. /******************************************************************************/8 |6 D# C. V4 i. [% M: k
  126. /*            PLL (clocked by HSE) used as System clock source                */
    ; c6 _2 e4 a. @' h
  127. /******************************************************************************/
    ) M7 r9 v) d6 O* u: w
  128.   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
    ( n" G! Z" Z6 C

  129. 3 a# o" L% B3 c% D+ B: B$ ^
  130.   /* Enable HSE and HSE BYPASS */& ]/ |$ e* b/ y6 o; n1 b; r, n/ ]
  131.   RCC->CR |= ((uint32_t)RCC_CR_HSEON | RCC_CR_HSEBYP);
    % y. F- s+ r5 L# B

  132. 4 \: @- `7 J- O
  133.   /* Wait till HSE is ready and if Time out is reached exit */8 k( ]( A; w3 E
  134.   do' m8 l  `, G+ W$ t- Y( V: w' M
  135.   {
    6 V2 t$ B' k7 N* W, N
  136.     HSEStatus = RCC->CR & RCC_CR_HSERDY;' X  A1 F  M+ i% o. \, j) s8 Q
  137.     StartUpCounter++;
    : Y2 u( F2 ?% ^. t
  138.   } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
    / v( x$ v: T- E' ~# ]+ _

  139. 0 L% T' M8 p7 b3 S7 K" I
  140.   if ((RCC->CR & RCC_CR_HSERDY) != RESET)
    1 |# V3 x+ q4 E3 p( x
  141.   {0 G9 {7 g% }- r7 }
  142.     HSEStatus = (uint32_t)0x01;
    $ ]; N4 i: F' M  V" h# [$ O. T7 k
  143.   }% K2 H' w# Y8 a- P
  144.   else. \2 w. A3 p+ i  m5 L
  145.   {' A+ F! A; W5 A+ D/ z6 C6 V
  146.     HSEStatus = (uint32_t)0x00;
    & Q& T, e: A3 k( m  T% t1 e8 {
  147.   }1 _. E5 I: c  T8 P4 X/ T

  148. / s. F/ J# V9 d) P
  149.   if (HSEStatus == (uint32_t)0x01)
    2 c/ E" }' _9 M* w; G+ u
  150.   {
    & f$ }" z2 O6 P
  151.     /* Select regulator voltage output Scale 1 mode */
    2 ]+ _' }4 J+ e4 }
  152.     RCC->APB1ENR |= RCC_APB1ENR_PWREN;% A1 P3 d% B' ]/ J) @/ i* x
  153.     PWR->CR |= PWR_CR_VOS;
    4 E. a5 a! T* U9 e* Q+ z$ f3 p( R, d

  154. 3 e& \5 m* c7 P
  155.     /* HCLK = SYSCLK / 1*/
    - q1 e+ K9 m6 R# g8 u+ a9 C
  156.     RCC->CFGR |= RCC_CFGR_HPRE_DIV1;+ u4 m+ f; \9 y+ F* c  d

  157. 3 d( d- k' I' r
  158.     /* PCLK2 = HCLK / 2*/$ V6 i) ]% x  y
  159.     RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;! P' c8 R& c8 [: W6 V- ^

  160. ) T5 @( g5 R' {: v( Y. B& |
  161.     /* PCLK1 = HCLK / 4*/
    . t/ l4 E) z4 `, n
  162.     RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;
    . S8 U6 S2 `' F. s5 m

  163. * ^6 u2 ?8 e+ {2 Y7 T5 [
  164.     /* Configure the main PLL */  q  c6 k+ [. j3 S
  165.     RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
    3 I) Y7 ^9 h$ f' D. F
  166.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);" A. F/ M  G% c$ C2 z
  167. 8 C5 K8 m" T+ l# Y
  168.     /* Enable the main PLL */: h; t5 l! T; _$ G0 Q: w
  169.     RCC->CR |= RCC_CR_PLLON;
    - V) V* v2 _# {4 S: L

  170. - u* A& W4 F, K) o2 C# W2 n, Y
  171.     /* Wait till the main PLL is ready */
    * Q' ?4 b8 N$ W5 Z- q& f5 I+ b
  172.     while((RCC->CR & RCC_CR_PLLRDY) == 0)
    , [/ O7 R  K& o% h
  173.     {- D; r2 y% C& ?$ L. A" ^. i3 a
  174.     }
    . G% J6 U+ F* [# [/ p, R

  175. ' E- n' k( |2 W
  176.     /* Configure Flash prefetch, Instruction cache, Data cache and wait state */8 z! V% |4 c* r) f- _
  177.     FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS;8 Z0 V& _, W6 H
  178. 0 {9 k, a& X/ d
  179.     /* Select the main PLL as system clock source */
    $ B0 D4 w9 H' T2 B! G8 a# c# D
  180.     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));; F9 m! H6 G6 K
  181.     RCC->CFGR |= RCC_CFGR_SW_PLL;$ l% S$ L" S! S* r; K6 P# d
  182. ; v' b- a" Y& S) y
  183.     /* Wait till the main PLL is used as system clock source *// ^" A3 m  x3 a5 ]  F
  184.     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
    ; A( t$ Y6 g5 c/ f) N0 ?
  185.     {$ L$ H" A# B; R) R: V2 M: T
  186.     }
    5 o9 o) z9 f: \3 c) ], {
  187.   }' T0 }, w6 }1 h% ?$ K1 j7 j
  188.   else
    ( \) U9 E* }8 E
  189.   { /* If HSE fails to start-up, the application will have wrong clock
    0 N- J/ r4 U0 b5 o! o6 L$ }
  190.          configuration. User can add here some code to deal with this error */
    . _0 B8 s% L% v5 `+ O7 V
  191.   }
    / W; r) a  n5 a9 p3 w  @$ @
  192. #else /* HSI will be used as PLL clock source */
    ) Q& ^/ i! B0 f- n
  193.   /* Select regulator voltage output Scale 1 mode */8 V( W  k" Z5 A
  194.   RCC->APB1ENR |= RCC_APB1ENR_PWREN;' G1 d; F# v) u! W5 j/ T  N
  195.   PWR->CR |= PWR_CR_VOS;
    + [7 ~% {/ Z' Z( ?
  196. 1 E6 g2 o# I1 Y, d
  197.   /* HCLK = SYSCLK / 1*/: V: A/ N$ Q) K8 l# Y; M, w! T6 j
  198.   RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
    9 \3 r, [& r  B' T) _
  199. 4 N; m$ F5 }: c# Q, z
  200.   /* PCLK2 = HCLK / 2*/
    ; ~- b; J  u9 ~  f; t3 S. o
  201.   RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;
    9 z3 j; b" ~( s

  202. 0 l3 g4 p" Y% @0 L+ w+ s
  203.   /* PCLK1 = HCLK / 4*/( [/ X+ _8 j2 d
  204.   RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;
    % O2 k, A- @: X+ ^! d8 y  u. S
  205. ) Y" O5 [( ~3 q7 t
  206.   /* Configure the main PLL */
    : u4 O" A9 p  x0 m; c7 Z/ \
  207.   RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) | (PLL_Q << 24);
    ) t3 {3 ?6 d; ~9 T( {5 y
  208. + W8 {3 V0 F. j
  209.   /* Enable the main PLL */
    * L( E+ R2 v% \/ `
  210.   RCC->CR |= RCC_CR_PLLON;
    ( T8 R, R' s7 F; R  G% n

  211. 8 M, z% z7 U  M( `2 N4 q1 a
  212.   /* Wait till the main PLL is ready */
    7 J2 g* F7 q+ P2 L/ d7 ?2 M
  213.   while((RCC->CR & RCC_CR_PLLRDY) == 0)
    % v/ ?+ n. q4 c1 y- c0 s4 V
  214.   {
    ( |/ \2 N' U/ t: p
  215.   }0 p% ]( \1 `/ ^

  216. ( o8 k: I/ O$ h5 S0 R( k3 ?! Z
  217.   /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
    5 Y; Y' i+ P& y5 r
  218.   FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS;$ ^  n3 [- ^2 s
  219. ! B  u) M9 F, d9 }
  220.   /* Select the main PLL as system clock source */
    3 c1 ?4 {5 F! w% F2 J4 I' c/ |8 b
  221.   RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    . h" Y/ Y- g8 Q0 [
  222.   RCC->CFGR |= RCC_CFGR_SW_PLL;9 |1 d! ^6 x1 Z% r0 D( P

  223. : n9 ]6 u' ^8 U* T& M2 [
  224.   /* Wait till the main PLL is used as system clock source */
    ' L8 V) @  f( o( ^0 I6 c) Q: f
  225.   while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
    1 E# L& }0 p! T, v7 X  X
  226.   {+ {" }9 [2 \- |
  227.   }% Y0 ]9 Q, F; a  s
  228. #endif /* USE_HSE_BYPASS */  
    6 u/ U, f! b# f" B' \3 W
  229. #endif /* STM32F40_41xxx || STM32F427_437xx || STM32F429_439xx || STM32F401xx || STM32F469_479xx */  $ r8 p, d7 r. c  [
  230. }
复制代码
1 g- L. U9 n  I2 N& w
先使能外部时钟 HSE,等待 HSE 稳定之后,配置AHB,APB1,APB2 时钟相关的分频因子,也就是相关外设的时钟。等待这些都配置完成之后,打开主 PLL 时钟,然后设置主 PLL 作为系统时钟 SYSCLK 时钟源。如果 HSE 不能达到就绪状态(比如外部晶振不能稳定或者没有外部晶振),那么依然会是 HSI 作为系统时钟。
3 G$ A6 ^2 o7 O1 Q7 j
+ z! ^- Q, X1 Q% i在这里要特别提出来,在设置主 PLL 时钟的时候,会要设置一系列的分频系数和倍频系数参数。大家可以从 SetSysClock 函数的这行代码看出:4 ?( d  f( u5 `, k2 q0 O$ H6 O, ]  p  T
6 O7 ^; O8 Y4 `' ?* n! o, A
  1.     /* Configure the main PLL */
      t2 |" b' V' q
  2.     RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |# c& P! ]) ~% {$ ~1 p' L
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码

- t6 B: Y8 C% L2 ]% s" I这些参数是通过宏定义标识符的值来设置的。默认的配置在 System_stm32f4xx.c 文件开头的地方配置。对于我们开发板,我们的设置参数值如下:9 M, q" \+ f. m+ Q3 B2 w0 r6 z- N: i
! `- U# a* Z) t  _9 K% S. @3 O
  1. #define PLL_M 8" D9 L- ?! h. N2 _2 m$ N
  2. #define PLL_Q 7
    1 X- H; p) Z* L* b1 V
  3. #define PLL_N 336
    7 n; ?: O# D: M6 @3 v  T8 U* o3 y
  4. #define PLL_P 2
复制代码
% F+ u" u) o! R/ \" S
这里还有个特别需要注意的地方,就是我们还要同步修改 stm32f4xx.h 中宏定义标识符HSE_VALUE 的值为我们的外部时钟:8 S/ a- v! r; N2 c3 Q! V$ H3 N6 h

& W% G( f* L# J8 K
  1. #if !defined (HSE_VALUE)9 ]1 p1 C* H; [, v
  2. #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */" q! N! E7 i2 K! y: h1 f
  3. #endif /* HSE_VALUE */
复制代码
2 G! K6 ~9 _) o
这里默认固件库配置的是 25000000,我们外部时钟为 8MHz,所以我们根据我们硬件情况修改为 8000000 即可。" v( c( J  O* ]3 n  U+ y
5 z3 @. [- y, ~# O# A% Z7 j
04. 时钟配置总结3 c' d- j  A% z/ K
最后我们总结一下 SystemInit()函数中设置的系统时钟大小:
1 `4 Y1 {+ a. g/ I8 T) RSYSCLK(系统时钟) =168MHz3 w9 m0 ~$ a2 Q- E* I# V- E
AHB 总线时钟(HCLK=SYSCLK) =168MHz) p, u+ M9 L: I) {" Y5 m
APB1 总线时钟(PCLK1=SYSCLK/4) =42MHz
  B, J3 q0 T0 X( mAPB2 总线时钟(PCLK2=SYSCLK/2) =84MHz
, K) i7 O4 Z0 e6 OPLL 主时钟 =168MHz
+ @! ~/ Q/ ~4 M, {, x. x5 C* n: Y. ^% `
7 x: I) B0 t$ ]$ C! h3 n
  Z( e& S6 D# A0 x
收藏 评论0 发布时间:2022-6-10 20:08

举报

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