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

【经验分享】STM32F4时钟系统

[复制链接]
STMCU小助手 发布时间:2022-3-31 11:00
01. STM32F4时钟系统概述4 ]9 ~' P  i, T
时钟系统是 CPU 的脉搏,就像人的心跳一样。所以时钟系统的重要性就不言而喻了。 STM32F4 的时钟系统比较复杂,不像简单的 51 单片机一个系统时钟就可以解决一切。于是有人要问,采用一个系统时钟不是很简单吗?为什么 STM32 要有多个时钟源呢? 因为首先 STM32 本身非常复杂,外设非常的多,但是并不是所有外设都需要系统时钟这么高的频率,比如看门狗以及 RTC 只需要几十 k 的时钟即可。同一个电路,时钟越快功耗越大,同时抗电磁干扰能力也会越弱,所以对于较为复杂的 MCU 一般都是采取多时钟源的方法来解决这些问题。
/ m" L! `8 m9 j; C2 |% D  a) X! u( V; f+ y$ u
02. STM32F4时钟系统图) i2 K2 N$ G% [, e% T" m

/ K1 H9 a- z8 o$ s; A6 ^ 20200829145259439.png
* [- v7 L3 S0 d- g. ?4 v' l5 S
3 G% R+ ~6 x0 Q: \在 STM32F4 中,有 5 个最重要的时钟源,为 HSI、HSE、LSI、LSE、PLL。其中 PLL 实际是分为两个时钟源,分别为主 PLL 和专用 PLL。从时钟频率来分可以分为高速时钟源和低速时钟源,在这 5 个中 HSI,HSE 以及 PLL 是高速时钟,LSI 和 LSE 是低速时钟。从来源可分为外部时钟源和内部时钟源,外部时钟源就是从外部通过接晶振的方式获取时钟源,其中 HSE 和LSE 是外部时钟源,其他的是内部时钟源。下面我们看看 STM32F4 的这 5 个时钟源,我们讲解顺序是按图中红圈标示的顺序:, L. S2 T5 D- I) W) A! r

$ s4 V' j+ J' d, s2 f2 h①、LSI 是低速内部时钟,RC 振荡器,频率为 32kHz 左右。供独立看门狗和自动唤醒单元使用。6 T; s2 P0 ]8 h3 i+ u
②、LSE 是低速外部时钟,接频率为 32.768kHz 的石英晶体。这个主要是 RTC 的时钟源。0 B7 B0 y3 V& q7 F
③、HSE 是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为 4MHz~26MHz。我们的开发板接的是 8M 的晶振。HSE 也可以直接做为系统时钟或者 PLL 输入。
) G0 e, M6 K$ V% {④、HSI 是高速内部时钟,RC 振荡器,频率为 16MHz。可以直接作为系统时钟或者用作 PLL输入。
( W  g+ Y" q7 B" W/ X* K) `7 \4 Z% ]7 g
⑤、PLL 为锁相环倍频输出。STM32F4 有两个 PLL:
# I/ [8 e$ \4 e, X9 [8 N  a0 f1) 主 PLL(PLL)由 HSE 或者 HSI 提供时钟信号,并具有两个不同的输出时钟。
6 m! O& N! x7 p3 Q- }& {第一个输出 PLLP 用于生成高速的系统时钟(最高 168MHz)9 N$ i; {# n' _" v/ W
第二个输出 PLLQ 用于生成 USB OTG FS 的时钟(48MHz),随机数发生器的时钟和 SDIO时钟。
9 [% e$ j6 e% }! c- f2)专用 PLL(PLLI2S)用于生成精确时钟,从而在 I2S 接口实现高品质音频性能。
& L% h% f& P" o! e$ X& t
: Z; L( D' F0 e4 h/ ~  r5 OA. 这里是看门狗时钟输入。从图中可以看出,看门狗时钟源只能是低速的 LSI 时钟。$ U2 Y/ j# p  M! D+ I+ A& B

* }# Q* H7 {8 g7 uB. 这里是 RTC 时钟源,从图上可以看出,RTC 的时钟源可以选择 LSI,LSE,以及HSE 分频后的时钟,HSE 分频系数为 2~31。
5 |2 c, |: X8 O% G: c- o& W
* ^1 B- h6 `  Q) _' s6 q4 c& B. hC. 这里是 STM32F4 输出时钟 MCO1 和 MCO2。MCO1 是向芯片的 PA8 引脚输出时钟。它有四个时钟来源分别为:HSI,LSE,HSE 和 PLL 时钟。MCO2 是向芯片的PC9 输出时钟,它同样有四个时钟来源分别为:HSE,PLL,SYSCLK 以及 PLLI2S时钟。MCO 输出时钟频率最大不超过 100MHz。, I! b' X& n4 Z+ t" Z6 g% W  _2 d$ a
7 @2 ]6 B8 c9 Q& c& B# o
D. 这里是系统时钟。从图 4.3.1 可以看出,SYSCLK 系统时钟来源有三个方面:HSI,HSE 和 PLL。在我们实际应用中,因为对时钟速度要求都比较高我们才会选用 STM32F4 这种级别的处理器,所以一般情况下,都是采用 PLL 作为 SYSCLK时钟源。根据前面的计算公式,大家就可以算出你的系统的 SYSCLK 是多少。
  R$ L5 e/ V. W" P* [7 V; W9 G0 o, f( A& k( {
E. 这里我们指的是以太网 PTP 时钟,AHB 时钟,APB2 高速时钟,APB1 低速时钟。这些时钟都是来源于 SYSCLK 系统时钟。其中以太网 PTP 时钟是使用系统时钟。AHB,APB2 和 APB1 时钟是经过 SYSCLK 时钟分频得来。这里大家记住,AHB最大时钟为168MHz, APB2高速时钟最大频率为84MHz,而APB1低速时钟最大频率为 42MHz。
4 `; |9 a5 r( t9 m% K1 B
, f5 @5 i/ B2 y1 NF. 这里是指 I2S 时钟源。从图 4.3.1 可以看出,I2S 的时钟源来源于 PLLI2S 或者映射到 I2S_CKIN 引脚的外部时钟。I2S 出于音质的考虑,对时钟精度要求很高。探索者 STM32F4 开发板使用的是内部 PLLI2SCLK。1 C3 a# V: [+ l7 p

4 ~$ i, m, E; {  qG. 这是 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。
  A! H% l4 r& P/ d4 I( z
9 f; z6 T' R  Y4 ^! V' PH. 这里是指外部 PHY 提供的 USB OTG HS(60MHZ)时钟。/ I: |. |! o) o0 x, z+ k% o9 d
8 n* N- f) O# k  c/ {9 F; A$ g
03. STM32F4时钟初始化配置
5 s" J# P/ `$ }" USTM32F4 时钟系统初始化是在 system_stm32f4xx.c 中的 SystemInit()函数中完成的。对于系统时钟关键寄存器设置主要是在 SystemInit 函数中调用 SetSysClock()函数来设置的。我们可以先看看 SystemInit ()函数体。1 K# C: H/ a: r- t& M! V

+ Y6 l8 o6 U# n/ {& Q
  1. /**2 k* ]! b* o, A. Q" d& R" {
  2.   * @brief  Setup the microcontroller system8 W5 E+ A. A$ Q, |3 e
  3.   *         Initialize the Embedded Flash Interface, the PLL and update the
    9 }* l% H9 ]0 r4 _8 Y
  4.   *         SystemFrequency variable.1 v) e' Z( E' V0 ?9 @0 y6 j4 r' w/ x
  5.   * @param  None
    0 c' o- M6 w! K3 p8 e2 n
  6.   * @retval None2 b6 a& k- L1 j
  7.   */5 V1 V/ Z5 Q9 g4 o' X
  8. void SystemInit(void)
    3 x3 y! g$ R# I& A! G$ l5 j+ M- `) A
  9. {9 L6 \' ^. u3 K/ W2 t2 ^; E8 @  s6 C$ k
  10.   /* FPU settings ------------------------------------------------------------*/
    ; J/ a* _) U; x* d6 J7 E: Y& Y- }% P
  11.   #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)" c7 g1 H1 ]3 C! d
  12.     SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
    ; P3 Y" t* I# E% `) Q4 z
  13.   #endif
    * {- }# X! n1 J# s
  14.   /* Reset the RCC clock configuration to the default reset state ------------*/" L8 |7 D, n2 A6 H3 `3 |* J+ N
  15.   /* Set HSION bit */
    4 n: b! W" T% ]: g
  16.   RCC->CR |= (uint32_t)0x00000001;5 a+ @6 o* n! g* ?. Z9 a5 Z' T$ |
  17. ! K6 [2 {& Y  {) C1 U1 B
  18.   /* Reset CFGR register */
    2 `& \  v! G# l6 a/ X. j
  19.   RCC->CFGR = 0x00000000;" y7 _4 D* Y4 [

  20. . y# X, X2 j/ t/ H
  21.   /* Reset HSEON, CSSON and PLLON bits */
    + Z2 P- @* J& x0 F5 J' h3 U
  22.   RCC->CR &= (uint32_t)0xFEF6FFFF;# c8 O4 ]* s, V9 T
  23. 2 e" J+ X9 a- R# J" {0 E8 T+ q6 P
  24.   /* Reset PLLCFGR register */
    6 g5 t6 |6 s5 Q! f# N
  25.   RCC->PLLCFGR = 0x24003010;( G5 O9 {  b( l  q' G
  26. ' `! }1 l' T4 e- W& g  U  W
  27.   /* Reset HSEBYP bit */
    - {) j& p, E+ a% f' H" ]6 I5 o
  28.   RCC->CR &= (uint32_t)0xFFFBFFFF;+ X6 i# o4 N, @! K3 [3 l% C

  29. . M, }. d- L' O6 N& W2 Z
  30.   /* Disable all interrupts */
      T$ J- h3 T: \& Z0 v. K7 r
  31.   RCC->CIR = 0x00000000;3 n" e6 v8 |& K% [5 ?6 T
  32. % v' f+ `4 ?: i8 J8 o
  33. #if defined(DATA_IN_ExtSRAM) || defined(DATA_IN_ExtSDRAM)/ G/ w! w" I# `* g9 A9 b
  34.   SystemInit_ExtMemCtl();
    * u; S! L& C; ]3 P. |# a6 h
  35. #endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */* ~' k  v- G3 x: F/ P  Y
  36. + D# n/ a. H8 j7 V0 x8 i
  37.   /* Configure the System clock source, PLL Multiplier and Divider factors,
    + E1 e" Q. C7 I
  38.      AHB/APBx prescalers and Flash settings ----------------------------------*/$ ?9 ~! V' s0 g+ K* p. W% K
  39.   SetSysClock();
    ( @0 B8 s9 h7 v$ }( [
  40. 8 e4 w2 T5 m. ?
  41.   /* Configure the Vector Table location add offset address ------------------*/
    + C' ?, C5 z0 `' _3 S
  42. #ifdef VECT_TAB_SRAM/ x# K3 p. {# Z, W2 Y" ^
  43.   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
      A/ L* E& x. I& o8 t1 B6 Z
  44. #else
    : p! _; ?3 J3 N) U( e% A
  45.   SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */1 n6 u. j' {2 C/ D1 P5 @* D
  46. #endif
    . |! I1 D% U  B
  47. }
    0 S, `% W+ V3 b, V7 k* O( p( H( o
复制代码

9 q, C0 S" B! Q$ Y; D在设置完相关寄存器后,接下来 SystemInit 函数内部会调用 SetSysClock 函数。
( w. q) t0 [) a! \. M9 T$ l4 i$ ^. c- N3 I
  1. /**+ Q8 t( G- z6 [- N6 m
  2.   * @brief  Configures the System clock source, PLL Multiplier and Divider factors, 3 Q$ E: B0 h: g/ S- `
  3.   *         AHB/APBx prescalers and Flash settings
    + a6 h5 t2 ]4 x* ]8 U% S6 s
  4.   * @Note   This function should be called only once the RCC clock configuration  
    - s4 m% i9 |; O4 A3 h2 W
  5.   *         is reset to the default reset state (done in SystemInit() function).   3 T% }2 Y' y! T4 ?3 G3 F3 L
  6.   * @param  None8 J( C, _  X" Q  s. o# w4 I. t
  7.   * @retval None5 Z8 M/ I/ w8 L  |
  8.   */
    9 p8 x; c; a1 P; ]6 j* P/ _- v& C% K
  9. static void SetSysClock(void)4 ~$ v# u  g  S% @8 A7 L8 H/ k
  10. {
    4 V) j& }' k% Z- X4 h3 ]
  11. #if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F401xx) || defined(STM32F412xG) || defined(STM32F413_423xx) || defined(STM32F446xx)|| defined(STM32F469_479xx)+ U7 n' j- f, e0 b9 [8 [
  12. /******************************************************************************/
    6 J# p" d8 _  @2 F+ Z5 K
  13. /*            PLL (clocked by HSE) used as System clock source                */
    ! ^# x. d" [4 P& \  \* r. J
  14. /******************************************************************************/
    9 I0 S! e4 U" v
  15.   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;; \0 s0 Y7 g% `! A- V

  16. 2 Y# ~9 v0 x8 i! J
  17.   /* Enable HSE */ //HSE时钟使能
    & e6 G( Z5 C9 Q. F
  18.   RCC->CR |= ((uint32_t)RCC_CR_HSEON);8 l! p9 ]) J( Y0 U
  19.   //等待HSE时钟稳定
    + D: q' e1 k3 ~# A1 K
  20.   /* Wait till HSE is ready and if Time out is reached exit */) d% w% T, o6 L4 @
  21.   do1 Q: a, m# N3 z# r; C4 Q9 d
  22.   {
    # b& W* s! Y1 N- w
  23.     HSEStatus = RCC->CR & RCC_CR_HSERDY;
    5 V$ y& H8 E3 w1 {; ~
  24.     StartUpCounter++;9 W/ t: |; ^; d
  25.   } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
    * X( g7 w# k4 w( `

  26. - J2 ^. b. X, }
  27.   if ((RCC->CR & RCC_CR_HSERDY) != RESET)
    3 f! a6 t* K+ N1 w. V0 g  c
  28.   {* O! ?+ U' |" J% d5 y1 i  r% c& s
  29.     HSEStatus = (uint32_t)0x01;' B$ v+ x/ t4 e/ @& J
  30.   }
    : j6 ?$ d3 f1 D- ?- Z
  31.   else
    6 u. |  B) i3 o9 l, x
  32.   {
    4 c- I8 V! W9 m: y% S& F* [* f7 H
  33.     HSEStatus = (uint32_t)0x00;
    2 x" b# G6 [' q$ r1 I  u
  34.   }
    6 t+ |# s1 I7 q
  35. 4 S/ a. M  G" G1 J0 l1 r1 h
  36.   if (HSEStatus == (uint32_t)0x01): m$ c4 B" r! u# ^9 `8 f6 ?; W
  37.   {
    2 r# a' r! o( N5 Y. d# W% y
  38.     /* Select regulator voltage output Scale 1 mode */0 U/ T& |! C  S
  39.     RCC->APB1ENR |= RCC_APB1ENR_PWREN;
    ( `2 F8 B! }+ B3 Q: u
  40.     PWR->CR |= PWR_CR_VOS;/ c6 v& y# q3 J/ ]" w* y# p
  41.         //AHB不分频$ U7 R6 x. r5 g3 H( T' w
  42.     /* HCLK = SYSCLK / 1*/
    9 ~* w8 L) v& }  o1 s% g' N
  43.     RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
    " V6 r2 l6 y7 z* p1 q

  44. 4 [! q. i- p. t" X) M& B
  45. #if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) ||  defined(STM32F412xG) || defined(STM32F446xx) || defined(STM32F469_479xx)   
    2 w) G, P( k$ |: u' u' _1 q
  46.     /* PCLK2 = HCLK / 2*/ //高速APB二分频  ?* I" }7 J' |1 I* }8 W: M
  47.     RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;! Z+ `$ K. d/ W" i
  48. $ S2 L9 w* W- o: G2 r
  49.     /* PCLK1 = HCLK / 4*/ //低速APB4分频
    5 i) _. U) P. ~+ E" w. y3 z2 `
  50.     RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;8 j8 V% v6 x) y* ?/ Y0 Q' m
  51. #endif /* STM32F40_41xxx || STM32F427_437x || STM32F429_439xx  || STM32F412xG || STM32F446xx || STM32F469_479xx */
    + _, f9 |; {3 P% E; d

  52. , @' }4 R" a4 q, F  W* A' m
  53. #if defined(STM32F401xx) || defined(STM32F413_423xx)
    ! ^0 v2 F# ]  o* j/ |. E
  54.     /* PCLK2 = HCLK / 1*/
      U) A9 a1 g1 n; H( W5 g- U& V
  55.     RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;' g' f, t7 {' q

  56. . o3 U0 z0 s( P) B7 K# o& |9 a" ~
  57.     /* PCLK1 = HCLK / 2*/
    - l3 o2 B2 _0 q0 J4 u
  58.     RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;
    ! {" N: A$ u* X; z' o1 t9 J7 x
  59. #endif /* STM32F401xx || STM32F413_423xx */
    3 }1 f7 s& g4 _' F8 V, t

  60. 9 |1 M/ ?: J% Q/ m" E2 R7 D% x8 S$ B
  61. #if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F401xx) || defined(STM32F469_479xx)    + w1 J" i4 p" K: b
  62.     /* Configure the main PLL */9 B1 X& H0 D4 W/ f5 ~3 f. C9 T, Z8 O
  63.     RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |3 O2 u4 V1 v1 P- J
  64.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
    ' M6 g' _6 z+ U" Z% N: E
  65. #endif /* STM32F40_41xxx || STM32F401xx || STM32F427_437x || STM32F429_439xx || STM32F469_479xx */0 Z7 I0 `( x9 U/ o8 L4 x

  66. ; a) A9 y. ]9 I* {% T" M
  67. #if  defined(STM32F412xG) || defined(STM32F413_423xx) || defined(STM32F446xx)) o( k. S8 n- i/ e7 v8 Y; Y
  68.     /* Configure the main PLL */
      S$ ~  A' [( x2 S8 V5 r
  69.     RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |; S1 [- [1 ~2 A" M, Y4 m7 i
  70.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24) | (PLL_R << 28);
    4 {2 O; B) S3 F7 O5 Y8 _
  71. #endif /* STM32F412xG || STM32F413_423xx || STM32F446xx */   
    , `7 F$ W  o. U, W1 O! t
  72. # s: {9 q- F5 a5 G3 R# i8 T
  73.     /* Enable the main PLL */
    ! m/ b+ H/ C1 N. i6 {
  74.     RCC->CR |= RCC_CR_PLLON;4 x$ d% b7 ~0 R4 ^' R( [  i$ y$ p
  75. 7 m& \3 g* s9 |! N; Y/ G
  76.     /* Wait till the main PLL is ready */9 C  o* i1 I* I) M% q( D! Z7 ]
  77.     while((RCC->CR & RCC_CR_PLLRDY) == 0)
    ! F# ]  y2 _* ?/ v. v% E
  78.     {' l5 O7 J& s# T
  79.     }" Q* {( u- j6 {" u( M. U/ x
  80. 6 p- i/ o! I( h3 ~+ \5 v/ z1 n
  81. #if defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F446xx) || defined(STM32F469_479xx)
    % ]7 v3 J7 @9 d
  82.     /* Enable the Over-drive to extend the clock frequency to 180 Mhz */
    4 d5 b  B# G0 D4 j( }* T. G! g
  83.     PWR->CR |= PWR_CR_ODEN;; ~2 L+ F* `  j6 T) Z$ i) r: n1 H
  84.     while((PWR->CSR & PWR_CSR_ODRDY) == 0)! ?) N. K+ f5 r: Q$ f
  85.     {! q$ q( H! X, w
  86.     }8 ]. Y( A2 F6 F  H6 V% M
  87.     PWR->CR |= PWR_CR_ODSWEN;% L* N+ i1 B  ?% W- {) q5 A" T2 j
  88.     while((PWR->CSR & PWR_CSR_ODSWRDY) == 0)( T# ~* }. f& S7 b2 \+ W, n
  89.     {) M' u( Q! j" G" q! j
  90.     }      9 ]6 Q8 D$ O2 e  q9 t; w* n
  91.     /* Configure Flash prefetch, Instruction cache, Data cache and wait state */, \* g# {$ }$ g, x- Q) X2 L) Z
  92.     FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;; S6 i( `% Y& @2 [' m  n
  93. #endif /* STM32F427_437x || STM32F429_439xx || STM32F446xx || STM32F469_479xx */( y( E& t% U0 \* T

  94. " R2 e- }3 e! ~/ O, M
  95. #if defined(STM32F40_41xxx)  || defined(STM32F412xG)  , f# B# X( Q  ?4 O. A
  96.     /* Configure Flash prefetch, Instruction cache, Data cache and wait state */6 f5 Y  L) E: |, L! X( e& S
  97.     FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
    + X" I5 y+ a( l7 @. m
  98. #endif /* STM32F40_41xxx  || STM32F412xG */
    0 G  }; X3 P, l* X2 d

  99. 3 T% I" Z4 b2 t
  100. #if defined(STM32F413_423xx)  2 L3 @0 f/ z% _" D% u5 e' z- F
  101.     /* Configure Flash prefetch, Instruction cache, Data cache and wait state */) p" M' O4 r; Y, A7 V
  102.     FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_3WS;
    9 E6 r8 n3 A" u7 [4 y* N3 X
  103. #endif /* STM32F413_423xx */- i: f4 g) l$ _6 a
  104. ' E% w& {) @( Z9 Y
  105. #if defined(STM32F401xx)
    0 g1 U. o+ T+ {4 Z2 J% v& c+ u4 U! R
  106.     /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
    * P0 ^9 H# F4 L6 M
  107.     FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS;" d$ q/ Q0 `5 R! ^  p8 f* k: C4 P
  108. #endif /* STM32F401xx */
    $ z  B7 X! I! t  s

  109. 3 F9 J+ O' h" K0 M, m# m6 R: D8 V
  110.     /* Select the main PLL as system clock source */
    3 ?, U2 e+ R1 P' F! Y; C" g
  111.     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));* b6 t, x; D! W2 J! v; l
  112.     RCC->CFGR |= RCC_CFGR_SW_PLL;
    ; _6 g; \$ w, K* t5 A/ J
  113. ( `3 E0 |8 C5 R! P3 t9 O
  114.     /* Wait till the main PLL is used as system clock source */& Z# [, v! d. e, |% ~  s
  115.     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);) _( C3 l) |# h6 x) h
  116.     {
    : z: Y" I- D  l, x
  117.     }
    ; y* z& L6 W8 Q9 c& G
  118.   }' T, `; ?+ W/ z) R
  119.   else- P& p. X( j, ^; H. Y+ [
  120.   { /* If HSE fails to start-up, the application will have wrong clock
    ! j3 M& S( h) ?# ]
  121.          configuration. User can add here some code to deal with this error */
    1 c# f) E) F. M! h, h. R
  122.   }
    $ o  A; B; _- s( B4 M
  123. #elif defined(STM32F410xx) || defined(STM32F411xE)
    2 p% b7 j# c# p, e; c- ]0 G
  124. #if defined(USE_HSE_BYPASS)
    - Z$ H, X* Q* M7 s2 P! H
  125. /******************************************************************************/) \/ ~2 r; ~; C* T$ V& V9 h; w# k  Q
  126. /*            PLL (clocked by HSE) used as System clock source                */
    7 ?0 P# G5 x0 s  H. R
  127. /******************************************************************************/" ~! ^4 S8 s  z2 Y
  128.   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
    5 K' Q( t: B7 r* N. O# s
  129. 1 D! o3 K  A( |1 V$ i
  130.   /* Enable HSE and HSE BYPASS */3 {* C* t$ J. W3 @3 k# r* Y4 \
  131.   RCC->CR |= ((uint32_t)RCC_CR_HSEON | RCC_CR_HSEBYP);
    4 E6 v& M3 W2 p6 B9 M+ _5 |

  132. 3 n/ k8 w* H! i# |" P
  133.   /* Wait till HSE is ready and if Time out is reached exit */) ~1 C& E2 _5 _+ c1 {3 m" [- i, ~
  134.   do# S- k* X; u* N
  135.   {4 r8 ~* W8 t; `7 o0 U# E! ~$ l* x
  136.     HSEStatus = RCC->CR & RCC_CR_HSERDY;
    3 Z* Z, {% \/ N# ?& }# o5 X& E
  137.     StartUpCounter++;
    4 |6 t& f2 @1 ^& n* @7 Q
  138.   } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
    & Y- H7 J# l" Y+ R; e' O

  139. $ a9 x9 ~. p1 s8 T9 z4 r
  140.   if ((RCC->CR & RCC_CR_HSERDY) != RESET)
    & _' z. W- t" |0 t7 {
  141.   {
    & W! w/ U( o2 C( {
  142.     HSEStatus = (uint32_t)0x01;
      m( M: K$ Z* a) z0 j
  143.   }3 x# \/ `6 V3 G* S" f" }* h/ k
  144.   else! N4 E$ K0 n% X2 K6 a# |
  145.   {1 h% r0 r- W2 D' @" Z5 E2 |- N
  146.     HSEStatus = (uint32_t)0x00;
    " p- i' [! Y8 K, h$ S
  147.   }
    5 |8 M7 J9 V1 B% H* m) ~! x

  148. 6 v- {' H! P! k) @; K1 ~* K
  149.   if (HSEStatus == (uint32_t)0x01)- q- Q& N6 k1 }- R
  150.   {
    8 k0 F0 f( ^& G0 ~6 ^' l
  151.     /* Select regulator voltage output Scale 1 mode */( f" d8 {+ A' @
  152.     RCC->APB1ENR |= RCC_APB1ENR_PWREN;
    ! @. J9 \# O9 @# c. R7 z$ G
  153.     PWR->CR |= PWR_CR_VOS;9 ?9 J  t, Z, a% _

  154. 3 T" ^% l; o7 @
  155.     /* HCLK = SYSCLK / 1*/
    % s1 S* m5 X" J1 A6 d1 h& j
  156.     RCC->CFGR |= RCC_CFGR_HPRE_DIV1;) b8 P0 a, s0 X% ~- D( w
  157. ' v7 s; r6 C: X% \0 a
  158.     /* PCLK2 = HCLK / 2*/
    3 t) E- D7 g4 [' m. P: k' Z
  159.     RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;+ B; l/ _$ f: l) p
  160. - l/ W& k& p6 J
  161.     /* PCLK1 = HCLK / 4*/; J/ U& d# Y5 D( M2 c) H
  162.     RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;
    + I' D" g, o6 J& P& J) G
  163. 0 z" N# N2 r) g$ J
  164.     /* Configure the main PLL */5 ^* a! K1 B7 @$ d. I7 G. u
  165.     RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |7 J  y0 J4 X6 P, i9 o; s
  166.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);) P/ L# ?: \; o! a* ^  S) H
  167. 3 I3 i: x* C% w9 }* @* R3 W  m& {8 b
  168.     /* Enable the main PLL */
    + S, K6 `; T# P6 e/ s
  169.     RCC->CR |= RCC_CR_PLLON;
    - h; ^! d, P5 u+ Q" s, y
  170. 8 V; s0 }; W% ?: O0 d, N4 o; W1 a: e3 j
  171.     /* Wait till the main PLL is ready */
    4 [4 Y, k) t. g
  172.     while((RCC->CR & RCC_CR_PLLRDY) == 0)
    ; S0 h6 R' i- \4 Q
  173.     {6 F/ ^$ ?/ c8 H) w& K+ Q: [
  174.     }
    5 [8 f: h9 T9 r' r

  175. 3 S( H6 L, N6 j- b' ?" M4 |
  176.     /* Configure Flash prefetch, Instruction cache, Data cache and wait state */8 }. N9 }8 C4 }6 ~5 w+ x
  177.     FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS;# [, J2 U( T& }6 z2 `

  178. * Q' Z& h: G2 U* B/ Y+ w  f5 `; w
  179.     /* Select the main PLL as system clock source */
    1 ~& @' D- K. C/ Z( t
  180.     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));6 [' c& m( }1 E3 G$ I+ U/ k9 `
  181.     RCC->CFGR |= RCC_CFGR_SW_PLL;2 _* b: q7 M8 m% d! }

  182. ! C$ g0 b7 Q  @8 L, q
  183.     /* Wait till the main PLL is used as system clock source */
    ; }/ ~1 a1 C$ O5 z
  184.     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);& Z" U: y3 M1 B5 E) t
  185.     {1 ~- r+ u0 p" F; D$ j: S: s5 u9 }
  186.     }9 `" j5 I+ x+ L& t  J
  187.   }; z& G5 h/ r" r
  188.   else
    * x2 R( w; ^' C2 J! i( n: w1 M  @
  189.   { /* If HSE fails to start-up, the application will have wrong clock/ L& m% b! `9 X7 {4 ~! ~
  190.          configuration. User can add here some code to deal with this error */
    2 M! n1 P( e5 P) i6 ~8 n
  191.   }
    + C3 e" @2 I6 [, `# i
  192. #else /* HSI will be used as PLL clock source *// S7 @1 F4 @2 h
  193.   /* Select regulator voltage output Scale 1 mode */
    " h% D* z5 C. {
  194.   RCC->APB1ENR |= RCC_APB1ENR_PWREN;7 [9 T: P' Z: Q4 }+ n) ~# a! f1 W
  195.   PWR->CR |= PWR_CR_VOS;. _' K( \- T/ U  j( L% i, d
  196. 0 b! v' s  E5 w; `
  197.   /* HCLK = SYSCLK / 1*/
    * g& D% U* R7 g% c' a. v; y
  198.   RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
    # K; `& n! S3 D. X7 n# X
  199. 4 G* g' Q( W4 r# h+ U( _0 o
  200.   /* PCLK2 = HCLK / 2*/
    / _) h5 d7 g4 N) u/ ]2 J/ R
  201.   RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;2 [0 U- N0 Q* E6 ^  P6 I

  202. : `; t6 h7 @" k* ]$ V
  203.   /* PCLK1 = HCLK / 4*/
    # U, M# J+ h. p+ h, g4 ]$ m
  204.   RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;- o% d/ [8 |0 N* Z+ W9 E

  205. - m+ o7 P) u( Y9 Q' F+ T. \' a# V
  206.   /* Configure the main PLL */% Q/ M9 u1 A8 k* r: o
  207.   RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) | (PLL_Q << 24); 2 b/ Q1 z! L, |% V

  208. 8 @7 K6 `" x4 G. m- k- j, c* {  A
  209.   /* Enable the main PLL */& M9 x4 Y; y, T6 ?- f$ L
  210.   RCC->CR |= RCC_CR_PLLON;7 N, C7 u8 ]1 k
  211. / Y. }, Z4 @0 {# O1 k$ T. v1 Y
  212.   /* Wait till the main PLL is ready */
    6 s: G6 w5 J; r  K/ u: k
  213.   while((RCC->CR & RCC_CR_PLLRDY) == 0): h" I. v7 ?, j. x# ]
  214.   {% H1 |* l8 ~+ @! g2 j
  215.   }
    * Y: c( r/ J) B9 h; k" ]. X

  216. : F7 @5 [. E0 z0 o8 `2 A
  217.   /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
    . u4 M, _* i% ~1 L% z7 e
  218.   FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS;. D0 ~6 ~. T/ A6 y: l6 I
  219. 5 K  S( j7 ^" C. h9 y* C6 ]
  220.   /* Select the main PLL as system clock source */
      A2 l  z) y1 E1 ^3 U( s+ b& `5 C& o6 o
  221.   RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));% Q/ n8 h+ Q- v! P+ p
  222.   RCC->CFGR |= RCC_CFGR_SW_PLL;! p  y8 @$ A5 `# k

  223. . [3 K# n1 q0 ?0 v; d8 `
  224.   /* Wait till the main PLL is used as system clock source */% J4 e7 r. _! B
  225.   while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
    , T5 {- Y* |2 o* {; _1 P6 \
  226.   {6 G! o6 o3 `- r+ ~0 F7 k; ?
  227.   }0 |& U7 s7 O! H, k
  228. #endif /* USE_HSE_BYPASS */  
    5 F4 |$ [1 v0 E* I" D
  229. #endif /* STM32F40_41xxx || STM32F427_437xx || STM32F429_439xx || STM32F401xx || STM32F469_479xx */  
    4 }/ E; }, I( I0 `% ?( ~* t
  230. }
复制代码
7 b6 Q2 J" A, I, F. i, ^
先使能外部时钟 HSE,等待 HSE 稳定之后,配置AHB,APB1,APB2 时钟相关的分频因子,也就是相关外设的时钟。等待这些都配置完成之后,打开主 PLL 时钟,然后设置主 PLL 作为系统时钟 SYSCLK 时钟源。如果 HSE 不能达到就绪状态(比如外部晶振不能稳定或者没有外部晶振),那么依然会是 HSI 作为系统时钟。
/ U# {' l7 b. U# p2 \7 x) ?& ~) T. u# Q6 n6 ]
在这里要特别提出来,在设置主 PLL 时钟的时候,会要设置一系列的分频系数和倍频系数参数。大家可以从 SetSysClock 函数的这行代码看出:/ F* z/ f  T( c2 {) g" _

) R/ A, I: g. L& O
  1.     /* Configure the main PLL */
    ; ^# I, X3 h% E" J! u* b
  2.     RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |. h  ?( O& M( x/ N2 _
  3.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码

; D: p" J$ i1 |3 R" @1 j这些参数是通过宏定义标识符的值来设置的。默认的配置在 System_stm32f4xx.c 文件开头的地方配置。对于我们开发板,我们的设置参数值如下:1 C1 x, T" d, `) u4 h1 Q, D5 K4 R

7 k% @  Z6 U! `3 X8 U
  1. #define PLL_M 8
    3 a! w/ G* M* i* L- d
  2. #define PLL_Q 7
    8 `+ ?) N% H5 V! u
  3. #define PLL_N 336
    + v! ~+ Q% [, b0 l6 J2 f
  4. #define PLL_P 2- R2 d% t8 F4 F$ X. x# q0 J
复制代码
; x' ^- R; F: D/ b. P
这里还有个特别需要注意的地方,就是我们还要同步修改 stm32f4xx.h 中宏定义标识符HSE_VALUE 的值为我们的外部时钟:' f3 f( u9 r2 F9 n9 \. V

8 x5 R, u& {$ `$ K
  1. #if !defined (HSE_VALUE)5 m& m- y2 D- U( J3 p4 {! }% F8 z. n
  2. #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */3 ^( E) J# u: W. N" t( ?
  3. #endif /* HSE_VALUE */
复制代码
" f. N1 g! h" E  e
这里默认固件库配置的是 25000000,我们外部时钟为 8MHz,所以我们根据我们硬件情况修改为 8000000 即可。  O1 r- q/ z7 k) v% V9 b6 j$ c
! ^2 l' X* V3 y! w" P+ H& v5 M
04. 时钟配置总结

& X& d% v$ x7 R: V$ y最后我们总结一下 SystemInit()函数中设置的系统时钟大小:$ s! o: F4 c' y( M) r
+ M9 P; p5 s3 B  U
SYSCLK(系统时钟) =168MHz
& x' G% J: e4 D- Z9 f
/ p2 Y7 n& g' ], c# P3 sAHB 总线时钟(HCLK=SYSCLK) =168MHz. u$ @/ X8 K$ s1 h

- R# U; b) p7 K- _! D. Q# `APB1 总线时钟(PCLK1=SYSCLK/4) =42MHz
4 E& ~) }$ Y: l+ M3 h( u. o' V
# W# |/ w# U: F. Q( W/ U$ kAPB2 总线时钟(PCLK2=SYSCLK/2) =84MHz/ D4 z$ R. M/ f6 n

' ~% V6 M1 x. ^8 ^- LPLL 主时钟 =168MHz' W/ f3 \; y+ u! b, @( D
& W. F1 O8 m6 @% p5 @
& J: u, z9 i( ~: T% ]# S# ~# }
! G; p; g1 W! |" g
收藏 评论0 发布时间:2022-3-31 11:00

举报

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