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

【经验分享】STM32F2系列系统时钟默认配置

[复制链接]
STMCU小助手 发布时间:2021-12-2 14:28

有个项目要用到STM32F207Vx单片机,找到网上的例子照猫画虎的写了几个例子,比如ADC,可是到了ADC多通道转换的时候就有点傻眼了,这里面的时钟跑的到底是多少M呢?单片机外挂的时钟是25M,由于该单片机时钟系统较为复杂,有内部高/低、外部高/低 、PLL锁相环时钟,又有AHB总线时钟、APB1/2时钟,而例子中很少讲到系统时钟的默认配置是怎么配置呢?那么就发点时间研究下这个单片机内部的复杂时钟系统吧。

下图是STM32F2系列的时钟树结构图:

1、内部高速时钟HSI、外部高速时钟HSE和PLL时钟PLLCLK时钟都接到了SW开关处,通过SW选择哪一路作为SYSCLK,SYSCLK经过AHB分频器进行分频得到HCLK,APB1和APB2是挂在总线AHB上的,通过APB1和APB2分频得出fpclk1和fpclk2。

2、PLL输入时钟源主要是靠外部高速时钟和内部高速时钟作为时钟源,通过PLLCFGR寄存器的bit22来选择具体哪一路作为时钟源。选择好了时钟源进入/M分频器,也就是PLLM进行分频,送入VCO,在通过xN,进行倍频,也就是PLLN1)通过/P进行分频(PLLP)得到PLLCLK;(2)通过/Q分频(PLLQ),得到PLL48CK。

然后边看代码边对照结构图进行分析,看软件如何给单片机配置系统时钟的。

, f* L$ y# A8 [2 M6 a9 |

301052464747191.jpg


5 @& D* @. @4 }, P; D

然后找到启动代码“startup_stmf32xx.s”,该代码是用汇编写的,可以看到,在调用main函数之前,是先调用了SystemInit函数的,该函数是在“system_stm32f2xx.c”中

  1. ; Reset handlerReset_Handler    PROC
    % G5 s9 D3 q0 {4 ]6 h5 y5 o
  2.                  EXPORT  Reset_Handler             [WEAK]
    ( F  f# z6 O4 W* e9 r$ x
  3.         IMPORT  SystemInit! x5 E) O; n( X/ U
  4.         IMPORT  __main
      b/ b  o' \& E0 ^
  5.                  LDR     R0, =SystemInit- _2 n; Q- m$ o9 }' Y9 w% B$ j2 A
  6.                  BLX     R0+ T# s$ g& w0 i3 [7 o' @
  7.                  LDR     R0, =__main, q5 D' P: i" c/ ^
  8.                  BX      R0  t$ o% L( e, I& w5 D8 x
  9.                  ENDP
复制代码

& r1 r7 t1 O7 y+ W; \

代码如下,变量直接赋个16进制的数,都不知道是啥意思,目的是干什么的,不知道,所以看下面代码时最好对照STM32F2x用户手册。当然这个只是一个初始化,待会主要看SetSysClock();这个函数,在调用该函数之前,我们知道单片机是先启用了内部高速时钟等一些配置。


% z. s! O7 U& H4 I: {. \' T

  1. void SystemInit(void)# P* s$ j( J% i; p# Y  c! m6 W
  2. {
    % N& e% x! O7 D9 |/ M: f3 i$ q
  3.   /* Reset the RCC clock configuration to the default reset state ------------*/
    ' x1 r# P  r; ?0 n' E. U- [4 H+ C
  4.   /* Set HSION bit */
    # {1 G8 f' Z  l6 D7 N
  5.   RCC->CR |= (uint32_t)0x00000001; //RCC_CR复位值0x0000_xx83,内部高速时钟使能,也就是说上电开始就使用内部高速时钟,16MHZ) W6 w& M6 p. h# a  [% G, m7 b

  6. 0 ~9 w* `1 v% I8 j* A9 ~
  7.   /* Reset CFGR register */
    - V& L2 D$ E) ]2 C2 {
  8.   RCC->CFGR = 0x00000000;    //通过开关SW选择内部高速时钟作为系统时钟16MHZ
    $ ^8 ?2 m) g/ L  B
  9.                                                         //AHB prescaler 不分频! y% P% [! X* ~& q  }5 I( P
  10.                                                       //APB Low speed prescaler (APB1) 不分频,fplck1 = 16MHZ4 z: s5 _" ]9 x) v* ]) k7 O
  11.                                                         //APB high-speed prescaler (APB2)不分频,fplck2 = 16MHZ
    & P9 @, J( E& P1 s; t; ^4 y
  12.                               //MCO1和MCO2时钟输出等配置可参考用户手册Page95- R% C# A! a7 g
  13. 7 y! y) W( k3 P9 ]) ~3 u( i
  14.   /* Reset HSEON, CSSON and PLLON bits */
    ' F+ Z. y5 \( O. p7 K# q  a* f% h
  15.   RCC->CR &= (uint32_t)0xFEF6FFFF;
    - W  n8 A6 \- Z8 ]  r$ \+ p5 @% H

  16. $ n0 d' I% G2 O! Z8 Z4 C
  17.   /* Reset PLLCFGR register */: C( r& l6 L* d; I5 T
  18.   RCC->PLLCFGR = 0x24003010; //RCC_CFGR复位值是0x2400_3010! o+ J, D9 A8 w4 e

  19. ' A: Q6 }3 i& M% Z
  20.   /* Reset HSEBYP bit */
    : O2 l: k3 ~0 R$ w+ P% ]( ^
  21.   RCC->CR &= (uint32_t)0xFFFBFFFF;  //对bit18 HSEBYP 设置为0,外部高速时钟被禁止9 `3 L- M& }8 U  M# c

  22. + i" o5 B  S4 ^
  23.   /* Disable all interrupts */
    ) k- N: q, l! W
  24.   RCC->CIR = 0x00000000;  //所有时钟中断都被禁止
    3 \1 q* D1 [( h" T. l

  25. * h: R0 c' x7 [* t0 u) s
  26. #ifdef DATA_IN_ExtSRAM! C9 J6 t9 Y7 s/ i* }
  27.   SystemInit_ExtMemCtl(); ; @* Q$ J  U( j. N2 ?$ ]5 t
  28. #endif /* DATA_IN_ExtSRAM */
    7 L! D2 [0 ~+ ~- H- o3 l
  29.          
    7 k. e! \( w) z. R( t' T; v) J% _
  30.   /* Configure the System clock source, PLL Multiplier and Divider factors, * K& z* J3 j9 k  T4 H+ P+ a6 E
  31.      AHB/APBx prescalers and Flash settings ----------------------------------*/
    : p& u5 B6 l. ~* X! O/ e
  32.   SetSysClock();9 ?. n5 y% U) \8 o1 A% Y

  33. * N$ }. I1 Q$ ?& Y! Z! B: {
  34.   /* Configure the Vector Table location add offset address ------------------*/! S" U( _! P! E3 F3 k, ^
  35. #ifdef VECT_TAB_SRAM& k8 w$ y1 N4 B% p+ w, K8 E7 }
  36.   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */) m" H) e" Q; d& Z* F
  37. #else5 f6 m1 W' G9 \0 [# {9 K
  38.   SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */! V% x6 T$ a. A" S& N. l0 ]
  39. #endif
    # J* I) r/ H7 [6 s$ {  f
  40. }
复制代码

0 r" B8 b  J3 R' p

在SystemInit(void)函数中在配置完一些参数后,还调用了SetSysClock()函数,该函数代码如下

  1. static void SetSysClock(void)
    4 g7 |7 l' }6 P/ L4 T* U
  2. {$ k+ w3 n, _+ L+ Y* P
  3. /******************************************************************************/
    : z; N+ @% y8 R
  4. /*            PLL (clocked by HSE) used as System clock source                */3 ^- m& J5 A) e9 k+ z1 X
  5. /******************************************************************************/
    0 k: `1 t+ Z  Q; P
  6.   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;6 r7 o: k+ [' O' i5 m
  7.   * G9 a( v- f( k7 h# q3 }, f
  8.   /* Enable HSE */
    ; o, ~; ~  `4 {% p) K# F
  9.   RCC->CR |= ((uint32_t)RCC_CR_HSEON);  //外部高速时钟使能,25MHZ
    " t4 `7 G; [  u( k

  10. 3 k, S% e: |  |1 b8 W1 ?9 i3 F
  11.   /* Wait till HSE is ready and if Time out is reached exit */  //外部时钟使能后,得需要一点时间到达各个端口
    6 f. N# }" i2 T& k
  12.   do
    6 u$ k3 R; q- `# E5 a
  13.   {7 P, H' U. n4 U& a& O
  14.     HSEStatus = RCC->CR & RCC_CR_HSERDY; //如果RCC_CR_HSERDY为0,说明外部时钟还没准备好,1说明外部时钟已准备好. l4 z3 P! O$ h& E8 N0 R
  15.     StartUpCounter++;//对读的次数进行累加,当累加次数到达1280次时,就意味着启动时间超时
    6 G# T  ^8 r0 m* @2 W2 c- _+ B
  16.   } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
    : K/ o" h4 p* D  \$ x& z
  17.   i- P  z3 [3 l, [
  18.   if ((RCC->CR & RCC_CR_HSERDY) != RESET)//这里判断上面的do while循环是因哪个条件结束的
    ; J- R* |2 _4 M! [) O6 f% {
  19.   {; E! Q, a# z# V
  20.     HSEStatus = (uint32_t)0x01;   //说明时钟已准备好了,才结束do whlie循环0 b5 H# ]& V, x' P1 Q/ K
  21.   }
    ! G5 Q8 E0 x0 ?: J$ K7 ^! @. A% G( v
  22.   else1 R" _2 t! |* {
  23.   {
    9 n/ g9 y3 Q5 j
  24.     HSEStatus = (uint32_t)0x00;  //说明是因为超时了而退出do while循环+ l" g5 s# |4 _2 j( ?; b$ K$ e
  25.   }6 ]1 u, [5 i0 [) \

  26. - ~" g* ]! p6 G1 P! w& D
  27.   if (HSEStatus == (uint32_t)0x01)
    % r2 J2 O) s9 f) N8 w
  28.   {
    ! i- r% A. r' X" q4 |
  29.     /* HCLK = SYSCLK / 1*/" z- ?( S" x2 o' q( z9 Z: ~
  30.     RCC->CFGR |= RCC_CFGR_HPRE_DIV1; //AHB不分频,AHB出来后时钟就是sysclk=120M
    1 s: b- w  U# o- |% t( R
  31.       
    / M1 Q) p. m8 d1 @) ]
  32.     /* PCLK2 = HCLK / 2*/1 @# E7 }: }) p4 u: U
  33.     RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;//APB2 2分频,fpclk2 = sysclk/2 = 60M
    . D: I$ w2 V, f& x4 t
  34.    
    + y& k& Q4 U) _, U% {/ ^
  35.     /* PCLK1 = HCLK / 4*/
    - s7 z" q6 H$ j
  36.     RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; //APB1 4分频,fplck1 = sysclk/4 = 30M
    " J$ `0 b- f, B. g" N
  37. & T, z: H1 \- S4 e; `
  38.     /* Configure the main PLL */ //主要对PLL和PPI2S 进行配置
    , R8 o( G. U+ l1 Z' ~! u, P
  39.     RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |8 t4 E* I  z4 {& @. A
  40.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
    9 M/ l* U! [$ R, \' N
  41. //配置完后RCC->PLLCFGR = 0x05403c19,然后对照寄存器RCC_PLLCFGR查看哪些位对应哪些功能- r6 g! v; m* l5 u6 x
  42. //通过bit5~bit0可计算出PLLM=25,那么input VCO = PLL input clock /PLLM = 25M/25 = 1M,对应时钟结构图中的/M8 A- m1 ?, G* T7 B7 c! f! V4 ]; z
  43. //通过bit14~bit6可计算出倍频因子PLLN = 240,那么VCO output clock = PLLN * input VCO = 240 * 1 = 240M,对应时钟结构图中的xN; ?" b2 R+ x, X+ o" |4 P. B
  44. //bit17~bit16可计算出分频因子PLLP = 2,那么PLLCLK = VCO output clock /PLLP = 240/2 = 120M; Y7 z) P. t- ~
  45. //bit22是选择给PLL输入的时钟源,输入时钟源有外部和内部高速时钟,这里选择的是外部高速时钟即PLL input clock = HSE =25M* _# |% u9 ]- h
  46. //bit27~24可计算出分频因子PLLQ = 5,那么PLL48CK = VCO output clock/PLLQ = 240/5 = 48M! `/ J; m( s. f; J
  47.         4 M1 \8 Z; {) Q
  48.     /* Enable the main PLL */
    0 `# |7 y) X4 s- p* S* ]
  49.     RCC->CR |= RCC_CR_PLLON; //使能PLL( w& r3 p0 U* ^. C; p$ `9 j. K
  50. - |) G  }9 [' \! T5 O. s2 V6 X
  51.     /* Wait till the main PLL is ready */) [" k5 O4 v- y$ Y9 s% |; q% l
  52.     while((RCC->CR & RCC_CR_PLLRDY) == 0)9 l) `6 h( x' w' N5 c
  53.     {, q0 \# D/ d2 \' P% q' i
  54.     }
    4 B7 c4 O0 ~" B  f! }+ X
  55.         //到这里RCC->CR已配置完,最终值0x03036783
    ! O: z; b8 }: x6 e# i0 Z' N
  56.         //通过查看用户手册知道,内部高速时钟、外部高速时钟、PLL时钟都已开启  B5 T' m" W3 x$ V9 t# w. J
  57.         6 [$ k8 _0 d8 ^+ U& v
  58.     /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
    & c+ V$ }9 Y, x
  59.     FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_3WS;; u8 ]4 h5 W6 b# ~5 @7 y

  60.   A1 h8 ?+ m$ A
  61.     /* Select the main PLL as system clock source */2 C, ^" G; f2 J0 ]; g/ S
  62.     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));. ~( T) H3 v% F: S
  63.     RCC->CFGR |= RCC_CFGR_SW_PLL;
    ( C& s" q% s! t9 v* y* K' X
  64.         ! o3 Y5 e- C# H8 A+ F7 H- n
  65.         //到这里RCC->CFGR已配置完,最终值是0x0000_940A- V9 K7 ]; ^9 ~! B
  66.         //通过查看用户手册,知道,PLL时钟作为系统时钟即120M
    7 p8 v* z8 Q+ o  G, n4 d' B
  67.         //AHB不分频,即HCLK = 120M4 z* z7 Q- y3 J: V# x& c7 [6 f
  68.         //APB1 4分频,即fpclk1 = 120/4=30M8 g4 ~" j- J, U1 p
  69.         //APB2 2分频,即fpclk2 = 120/2=60M" a, K3 f# n- h; j3 q9 f* Y4 F
  70. 0 G2 s  D; _& t" w' Y9 j8 @6 L! [( \
  71.     /* Wait till the main PLL is used as system clock source */, Y0 ?" _& {- s: T* W
  72.     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);2 \5 [8 V+ @3 F
  73.     {" \4 B) `; l# c. t
  74.     }1 |; y8 q' w6 [
  75.   }9 n; o  Y7 @, H# h% |0 ?# \$ J
  76.   else
    6 ]. w# q& T$ h
  77.   { /* If HSE fails to start-up, the application will have wrong clock: C" c& d& k8 b& l' `5 \8 I: X7 Z
  78.          configuration. User can add here some code to deal with this error */! m9 g7 V0 }# i6 V5 |: S7 @5 g0 N  B
  79.   }
    / T2 Q- G. V+ A8 _' l

  80. 3 P+ A7 Z; L, Q8 }; J5 o6 J
  81. }
复制代码


/ ?: o; X; E  t3 t

OK,分析完这段代码后,调用系统固件函数后,现在知道了时钟树结构图中右边出来的时钟是多少MHz了吧。

总结:

1、使用的是外部时钟25MHZ,通过PLL进行分频倍频分频得到PLLCLK 120M,PLLCLK作为系统时钟SYSCLK。

2、APB1出来是30M,也就是FPCLK1。

3、APB2出来是60M,也就是FPCLK2。

) Q% c! s2 N* c8 X; b0 s, V
" H. L/ N9 L7 k
6 s6 L% g; Q5 x
7 A9 |+ ^: M. v3 p6 o
收藏 评论0 发布时间:2021-12-2 14:28

举报

0个回答

所属标签

相似技术帖

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