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

【经验分享】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  x  r3 f7 Y( ?5 _2 P

301052464747191.jpg


# Q# ^3 x3 \# c5 C

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

  1. ; Reset handlerReset_Handler    PROC0 T7 d4 _$ Y  Z: S4 n1 Y
  2.                  EXPORT  Reset_Handler             [WEAK]
    ! w4 @2 E% A, W# E4 v
  3.         IMPORT  SystemInit
    + U4 v4 k+ b" A8 X) E, G. ]+ b( D
  4.         IMPORT  __main. X8 v+ x0 u( m: `3 b
  5.                  LDR     R0, =SystemInit
    8 l3 [# b/ ~7 @7 S/ O9 Z! e/ x
  6.                  BLX     R08 `3 N. _* L6 g3 Q
  7.                  LDR     R0, =__main
    ( E( q) O! G1 i" y! _% M$ k0 v- f" i
  8.                  BX      R02 T5 c# `. `5 w# v3 [
  9.                  ENDP
复制代码

' w" Z. A$ x2 A

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


# D, V! k. P' W4 \" Z7 U1 S2 _# g( o

  1. void SystemInit(void)1 i' i  n* m0 r
  2. {  R1 o6 Z, e$ {3 Y5 C" y! w
  3.   /* Reset the RCC clock configuration to the default reset state ------------*/2 K$ N7 J( I; z$ J4 z& L* D6 z- j' Z
  4.   /* Set HSION bit */
    & N* r) j) N0 H& R
  5.   RCC->CR |= (uint32_t)0x00000001; //RCC_CR复位值0x0000_xx83,内部高速时钟使能,也就是说上电开始就使用内部高速时钟,16MHZ- ]3 Y1 N2 k2 |: h: t  ^

  6. 8 t! |7 q# v- z* D
  7.   /* Reset CFGR register */! M, q' m  y7 W4 I
  8.   RCC->CFGR = 0x00000000;    //通过开关SW选择内部高速时钟作为系统时钟16MHZ2 f& m0 b, d7 n3 I+ x
  9.                                                         //AHB prescaler 不分频
    & y; W' s7 F, D' r9 i9 I
  10.                                                       //APB Low speed prescaler (APB1) 不分频,fplck1 = 16MHZ
    + W( _! J5 F! ]: Q( @
  11.                                                         //APB high-speed prescaler (APB2)不分频,fplck2 = 16MHZ9 ?2 n& k% [. v9 {
  12.                               //MCO1和MCO2时钟输出等配置可参考用户手册Page95
    ; E5 ~+ t5 ^% W
  13. 5 @, X6 R$ k! \
  14.   /* Reset HSEON, CSSON and PLLON bits */, K5 W/ ~9 w: ~  `  ~+ h& @; h/ Q
  15.   RCC->CR &= (uint32_t)0xFEF6FFFF;
      O: s* H, V/ Y9 y6 J2 ]: ]
  16. : {; z) L. ]# g- @, H7 G
  17.   /* Reset PLLCFGR register */; e' s8 I+ M. E9 \: ?! J
  18.   RCC->PLLCFGR = 0x24003010; //RCC_CFGR复位值是0x2400_30105 Z3 F: _( u- q0 e2 Y: ~! g% t

  19. 1 o% b. ^  O+ b5 H9 x+ W
  20.   /* Reset HSEBYP bit */
      J+ V% H; ~, H
  21.   RCC->CR &= (uint32_t)0xFFFBFFFF;  //对bit18 HSEBYP 设置为0,外部高速时钟被禁止9 ~7 Z- `0 u: C6 J! H

  22. ) Z6 g8 Q3 c2 I7 D
  23.   /* Disable all interrupts */
    & z7 q( J9 C: N8 q
  24.   RCC->CIR = 0x00000000;  //所有时钟中断都被禁止
    / d9 |# z! ]+ M# l

  25. ) x. u9 D1 U; ?2 k8 H" v8 V8 v
  26. #ifdef DATA_IN_ExtSRAM
    1 R8 D, i9 k. q! O  I$ J$ p
  27.   SystemInit_ExtMemCtl();
    - L1 @5 y% G$ [+ h6 S: Q
  28. #endif /* DATA_IN_ExtSRAM */; y+ }* A7 n4 |+ V3 R
  29.          
    8 Z! n; N8 F* s  x" P
  30.   /* Configure the System clock source, PLL Multiplier and Divider factors,
    , X' Y) o3 |( g; e- S3 B" L  _% ~
  31.      AHB/APBx prescalers and Flash settings ----------------------------------*// G- Q( @- k# C9 ?$ }: |( F  z
  32.   SetSysClock();5 w; F! n  Z  s0 n/ N1 V: @% J( ]

  33. 0 c5 y. `4 @5 @
  34.   /* Configure the Vector Table location add offset address ------------------*/% X, l% L7 ^% ~* R, C$ V' t0 D5 r& \
  35. #ifdef VECT_TAB_SRAM8 w6 s# ?+ @* u
  36.   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
    6 U' d/ S. Z- n6 B
  37. #else
    ) w; C7 d2 r$ S+ P0 ?6 x5 l) t
  38.   SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */) |1 Z1 V' W6 ?
  39. #endif3 o- K2 }9 Z& k8 R( ^
  40. }
复制代码

. T) u. o, G% D2 t

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

  1. static void SetSysClock(void)) M4 L7 J. Y0 J9 ?9 u2 ?# m' I
  2. {
    ' I3 Q" u6 S* q/ R! d2 g
  3. /******************************************************************************/
    ) p0 B7 ?9 L( N7 x5 `* w
  4. /*            PLL (clocked by HSE) used as System clock source                */$ {& I& ^' W7 V' U* l9 j  z7 L
  5. /******************************************************************************/. W9 E; q# V- K+ \7 ~+ W8 ?
  6.   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
    ) ]4 i3 ]7 a4 y1 K
  7.   : s9 H+ T0 D  a6 ^% W( r5 ]
  8.   /* Enable HSE */. p3 Z. k# Y7 K/ z( |
  9.   RCC->CR |= ((uint32_t)RCC_CR_HSEON);  //外部高速时钟使能,25MHZ2 p# ?$ N+ Q" r( q! J
  10. 5 t4 H6 K. n+ t% C6 d1 A9 ?
  11.   /* Wait till HSE is ready and if Time out is reached exit */  //外部时钟使能后,得需要一点时间到达各个端口  i/ z# d" d) U! W& s
  12.   do
    , H3 @6 G  w7 ?
  13.   {- [, P  d) I$ B. k1 z5 d0 d* p
  14.     HSEStatus = RCC->CR & RCC_CR_HSERDY; //如果RCC_CR_HSERDY为0,说明外部时钟还没准备好,1说明外部时钟已准备好
    ) O! x5 h+ ~. ^( \" {# G
  15.     StartUpCounter++;//对读的次数进行累加,当累加次数到达1280次时,就意味着启动时间超时2 N, n, q1 H7 [7 ~' t5 @( i6 y' a
  16.   } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
    " p9 Q; G0 I7 @2 _5 M; u
  17. " B3 X0 N. O& u1 q* X2 \
  18.   if ((RCC->CR & RCC_CR_HSERDY) != RESET)//这里判断上面的do while循环是因哪个条件结束的
    # W1 R5 f! {1 T2 J6 V
  19.   {9 [. l8 z! ?3 b
  20.     HSEStatus = (uint32_t)0x01;   //说明时钟已准备好了,才结束do whlie循环
    % r+ O) ?& g: i4 ]9 b9 b- ~& S/ Z2 V
  21.   }3 z; t4 t# ~, S- C& e  n
  22.   else" R. c- U" I" |- B) ?, G) X
  23.   {. y# L, Q6 f5 d5 w1 ~
  24.     HSEStatus = (uint32_t)0x00;  //说明是因为超时了而退出do while循环8 C6 \# b- G5 H! G" n! e% v# b
  25.   }
    3 M) Q8 K) I, u0 X
  26. 4 L7 H/ ]2 g! u: O
  27.   if (HSEStatus == (uint32_t)0x01)
    % w2 t2 Y, y0 F" [
  28.   {
    0 `" [; a. n8 ]8 w$ ^) F, I2 S2 P, y
  29.     /* HCLK = SYSCLK / 1*/; M6 F5 U: S  R' _- ]9 x" d1 [
  30.     RCC->CFGR |= RCC_CFGR_HPRE_DIV1; //AHB不分频,AHB出来后时钟就是sysclk=120M# y; q3 r# T7 r$ w, ^/ u* \% D+ V* x
  31.       
    ; n" K) Y$ |1 Q
  32.     /* PCLK2 = HCLK / 2*/9 a* ^+ d& i. x" X
  33.     RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;//APB2 2分频,fpclk2 = sysclk/2 = 60M! {0 E" I0 j7 Y" c  P
  34.     + U8 j9 V- o, [+ C" X! w2 O4 A
  35.     /* PCLK1 = HCLK / 4*/
    # Q& Z8 y# _4 `6 S$ k
  36.     RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; //APB1 4分频,fplck1 = sysclk/4 = 30M7 D  M0 G" B, E  @6 Q

  37. - s! D1 D' z. e' H! c9 h5 Q
  38.     /* Configure the main PLL */ //主要对PLL和PPI2S 进行配置& ^6 A9 T2 ^- d4 N+ r
  39.     RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |+ ?1 J+ J* |9 D! g
  40.                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);7 Z) t; ]" u) D% y3 A
  41. //配置完后RCC->PLLCFGR = 0x05403c19,然后对照寄存器RCC_PLLCFGR查看哪些位对应哪些功能
    $ M0 a) q7 O& w5 r! G) M3 Q7 x: g! V
  42. //通过bit5~bit0可计算出PLLM=25,那么input VCO = PLL input clock /PLLM = 25M/25 = 1M,对应时钟结构图中的/M
    + a% k0 v+ \. W0 R. |" V' u7 B$ D
  43. //通过bit14~bit6可计算出倍频因子PLLN = 240,那么VCO output clock = PLLN * input VCO = 240 * 1 = 240M,对应时钟结构图中的xN
    ! k, O0 K: Y  z, a" x
  44. //bit17~bit16可计算出分频因子PLLP = 2,那么PLLCLK = VCO output clock /PLLP = 240/2 = 120M2 \- N; ?' R1 f! [$ \; j
  45. //bit22是选择给PLL输入的时钟源,输入时钟源有外部和内部高速时钟,这里选择的是外部高速时钟即PLL input clock = HSE =25M# B! E$ m0 z+ C8 f
  46. //bit27~24可计算出分频因子PLLQ = 5,那么PLL48CK = VCO output clock/PLLQ = 240/5 = 48M
    " V3 @# V. R0 `' i9 B
  47.         
    ( h  q, Z+ ?, q. g- P6 U
  48.     /* Enable the main PLL */6 f) a8 ?1 l/ v+ Z2 ?6 h* z% {
  49.     RCC->CR |= RCC_CR_PLLON; //使能PLL% O  Q9 i* t$ v$ X  Z) y' c: O, r

  50. ' ^! x! t) V; i; j" D8 u
  51.     /* Wait till the main PLL is ready */! q% O# v% c1 n" [2 e" J
  52.     while((RCC->CR & RCC_CR_PLLRDY) == 0)4 e, V; Y) w( s& u$ g
  53.     {( b) ]4 P2 H. W: W$ q
  54.     }' e3 A* e0 h) N6 Q
  55.         //到这里RCC->CR已配置完,最终值0x03036783. _% u$ V, Y2 H3 g8 W6 s% X) `
  56.         //通过查看用户手册知道,内部高速时钟、外部高速时钟、PLL时钟都已开启+ ^; R4 {& [! a
  57.         4 e, I; w/ i+ J4 n' n, {0 `
  58.     /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
    : ]) L# S  ^# t+ [& Q) N! r
  59.     FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_3WS;
    4 S! p- T0 d6 ?

  60. * [% ]: ~" V* f1 X
  61.     /* Select the main PLL as system clock source */+ K5 `. \' D# J0 h8 l: L
  62.     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    * _8 w0 E. [) M+ P8 y
  63.     RCC->CFGR |= RCC_CFGR_SW_PLL;1 e* T& H' O6 @. i/ A
  64.         ' }+ U4 ^: c0 m6 o% t9 g
  65.         //到这里RCC->CFGR已配置完,最终值是0x0000_940A" f: x# z6 }' @8 v+ y( b% w
  66.         //通过查看用户手册,知道,PLL时钟作为系统时钟即120M0 Q+ c5 k) i; P0 ?* {$ D
  67.         //AHB不分频,即HCLK = 120M9 o# G& ]% Q  S+ z! \
  68.         //APB1 4分频,即fpclk1 = 120/4=30M1 C7 a' L+ Q4 ?8 g! t- i
  69.         //APB2 2分频,即fpclk2 = 120/2=60M
    " M' [6 I1 {9 L# T* s

  70. 7 y% g7 w7 A* n+ j4 C4 r' R& [' O7 E
  71.     /* Wait till the main PLL is used as system clock source */: M$ D, S1 c$ F7 A3 u! X# F/ O
  72.     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
    - h: y$ U' j" W, p; \* d
  73.     {9 O0 ]. Z7 G& r, a
  74.     }" a' s3 T1 R$ ?" x" H4 h, K$ J4 Z
  75.   }
    % t0 e( A8 o: ~& `
  76.   else  m: _5 [5 G" S8 ]3 E( e, Q
  77.   { /* If HSE fails to start-up, the application will have wrong clock
    / n; F6 P( ~( A3 l' a2 ^+ O
  78.          configuration. User can add here some code to deal with this error */; G+ h) l0 ]) R, U0 ]
  79.   }
    8 _: X* r' ^' V7 r
  80. 2 e% ]2 e( b# v9 x9 x
  81. }
复制代码


, U9 z) B: Q6 ?* A$ P

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

总结:

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

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

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

: l( E$ v0 N- ^
. a/ _. j: @. y& }1 V

/ a( `) R% v  f& A- }2 P) z& r- l% ~- E1 y' g' U
收藏 评论0 发布时间:2021-12-2 14:28

举报

0个回答

所属标签

相似技术帖

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