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

【经验分享】STM32F205时钟配置

[复制链接]
STMCU小助手 发布时间:2021-12-3 16:00

下图是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。

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

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

  1. <font color="#000000">; Reset handler; E, E; |- `; K+ d% d5 C7 f
  2. Reset_Handler PROC
    + C7 d) {: Y4 n9 j. K
  3. EXPORT Reset_Handler [WEAK]
    4 [! E3 n/ X5 m2 \1 }2 }
  4. IMPORT SystemInit
    - j+ t0 k" l  n
  5. IMPORT __main
    8 {0 k7 ^2 d4 f! e: |2 S! j) k0 h
  6. LDR R0, =SystemInit
    : {! O( F" c1 ~& f& i
  7. BLX R04 o2 O% l+ Z1 j0 H5 S: D. Y
  8. LDR R0, =__main
    2 v2 H5 H# t& ~2 A! h  ?& v
  9. BX R0
    1 U4 ^0 r4 U4 I* m( T$ q
  10. ENDP</font>
复制代码

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

  1. <p style="line-height: 26px;"><font face="-apple-system, " "=""><font style="font-size: 16px" color="#000000">void SystemInit(void)+ j1 z  U6 O3 A% d) I
  2. {  @; x. A. u: Y; c0 {! }
  3. /* Reset the RCC clock configuration to the default reset state ------------<i>/
    / f, q- p+ U. b* H( K: W
  4. /</i> Set HSION bit */1 Z$ A- I1 M3 Z( C" n
  5. RCC->CR |= (uint32_t)0x00000001; //RCC_CR复位值0x0000_xx83,内部高速时钟使能,也就是说上电开始就使用内部高速时钟,16MHZ</font></font></p><p style="line-height: 26px;"><font face="-apple-system, " "=""><font style="font-size: 16px" color="#000000">/* Reset CFGR register */
    . m2 g% @! L" I0 Q# _4 b5 j& }
  6. RCC->CFGR = 0x00000000; //通过开关SW选择内部高速时钟作为系统时钟16MHZ/ ?( d( ?! V: e3 {1 w7 K
  7. //AHB prescaler 不分频& w2 y( B; i) i- z' {) h
  8. //APB Low speed prescaler (APB1) 不分频,fplck1 = 16MHZ/ _0 D* h) B$ }6 v
  9. //APB high-speed prescaler (APB2)不分频,fplck2 = 16MHZ9 ]/ t: R( v/ G5 p" r' m# h
  10. //MCO1和MCO2时钟输出等配置可参考用户手册Page95</font></font></p><p style="line-height: 26px;"><font face="-apple-system, " "=""><font style="font-size: 16px" color="#000000">/* Reset HSEON, CSSON and PLLON bits */$ g# \% ~. J5 o
  11. RCC->CR &= (uint32_t)0xFEF6FFFF;</font></font></p><p style="line-height: 26px;"><font face="-apple-system, " "=""><font style="font-size: 16px" color="#000000">/* Reset PLLCFGR register *// j1 }/ T4 F2 C) S
  12. RCC->PLLCFGR = 0x24003010; //RCC_CFGR复位值是0x2400_3010</font></font></p><p style="line-height: 26px;"><font face="-apple-system, " "=""><font style="font-size: 16px" color="#000000">/* Reset HSEBYP bit */2 n* G# ~  Y5 l3 N6 M( T
  13. RCC->CR &= (uint32_t)0xFFFBFFFF; //对bit18 HSEBYP 设置为0,外部高速时钟被禁止</font></font></p><p style="line-height: 26px;"><font face="-apple-system, " "=""><font style="font-size: 16px" color="#000000">/* Disable all interrupts */" k1 ~, O+ g& _0 s. c
  14. RCC->CIR = 0x00000000; //所有时钟中断都被禁止</font></font></p><p style="line-height: 26px;"><font face="-apple-system, " "=""><font style="font-size: 16px" color="#000000">#ifdef DATA_IN_ExtSRAM1 h' }! X, u4 R; Y" B8 v
  15. SystemInit_ExtMemCtl();
    & N+ P& ]4 R% b
  16. #endif /* DATA_IN_ExtSRAM */</font></font></p><p style="line-height: 26px;"><font face="-apple-system, " "=""><font style="font-size: 16px" color="#000000">/* Configure the System clock source, PLL Multiplier and Divider factors,# U5 |) \) f9 ?
  17. AHB/APBx prescalers and Flash settings ----------------------------------*/
    7 U8 T2 _( `8 c/ \8 d/ z5 Q
  18. SetSysClock();</font></font></p><p style="line-height: 26px;"><font face="-apple-system, " "=""><font style="font-size: 16px" color="#000000">/* Configure the Vector Table location add offset address ------------------<i>/
    4 X+ i  ^" }' _, e- S  x" g
  19. #ifdef VECT_TAB_SRAM
    % l, L6 O- J: z- D8 b0 @0 n( B5 n
  20. SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /</i> Vector Table Relocation in Internal SRAM <i>/
    2 k- P9 H  M5 K4 _+ B, x' b* W  T
  21. #else" ?/ ?5 r1 Y' Z; m" O
  22. SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /</i> Vector Table Relocation in Internal FLASH */2 g. ?8 [* u& L9 ~* Q3 P# C
  23. #endif2 T4 `1 {0 o& M. A2 v6 D- g
  24. }</font></font></p>
复制代码
# D7 F& g, @, a( ?1 Z$ w3 K

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

+ ~8 O& M: Z- ?. O' E7 m5 Z
static void SetSysClock(void)
0 G$ O0 d! }8 A{1 N$ A, N- e( ~& o( D  I3 G9 U, W
/*****************************************************************************/
8 X! ^5 Q; U' r' k: d: B/
PLL (clocked by HSE) used as System clock source /+ s) \0 t" y* ?4 I- X1 D
/
*****************************************************************************/
, `( R% H+ [3 q: X+ j  L__IO uint32_t StartUpCounter = 0, HSEStatus = 0;

/* Enable HSE */: T/ R0 P8 H( g+ F, w* ?/ H
RCC->CR |= ((uint32_t)RCC_CR_HSEON); //外部高速时钟使能,25MHZ

/* Wait till HSE is ready and if Time out is reached exit */ //外部时钟使能后,得需要一点时间到达各个端口; f# _3 M/ I6 a* V- b9 y
do
+ u5 y) F# U+ I( P% @. D{) i# T( v# R; |9 k
HSEStatus = RCC->CR & RCC_CR_HSERDY; //如果RCC_CR_HSERDY为0,说明外部时钟还没准备好,1说明外部时钟已准备好; r/ X+ g! A3 f. z# z, t& m( d
StartUpCounter++;//对读的次数进行累加,当累加次数到达1280次时,就意味着启动时间超时+ t9 P1 |) u- h4 j1 N. c0 F+ v
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

if ((RCC->CR & RCC_CR_HSERDY) != RESET)//这里判断上面的do while循环是因哪个条件结束的- W. y6 L& X) U
{$ [% k* K4 z8 z+ U) a, b6 g
HSEStatus = (uint32_t)0x01; //说明时钟已准备好了,才结束do whlie循环7 R) p& N5 u- H
}
6 z  C0 N6 H6 V( Z7 [else
- g! Q6 Y4 f4 p" \, m8 q{; }  R8 R9 ^3 L/ q
HSEStatus = (uint32_t)0x00; //说明是因为超时了而退出do while循环. y$ w9 S# g4 W- w
}

if (HSEStatus == (uint32_t)0x01)+ j( [, b# X, a) F
{
1 c# G. R. J' j/* HCLK = SYSCLK / 1*/
) a- l+ K/ v0 a% [7 ^% t1 r9 oRCC->CFGR |= RCC_CFGR_HPRE_DIV1; //AHB不分频,AHB出来后时钟就是sysclk=120M

  1. /* PCLK2 = HCLK / 2*/
    6 W3 z2 m3 ^5 \. S* b3 o
  2. RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;//APB2 2分频,fpclk2 = sysclk/2 = 60M7 x& y' y+ V2 L5 |" U

  3. 7 E7 Y% x) g' }. d3 ^4 H
  4. /* PCLK1 = HCLK / 4*/
    7 }' ]; Q9 p. Z$ c8 L6 y0 V& d. r
  5. RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; //APB1 4分频,fplck1 = sysclk/4 = 30M+ J0 G5 S- E: y
  6. % a/ Y, U3 \! l! _2 D$ K
  7. /* Configure the main PLL */ //主要对PLL和PPI2S 进行配置
      B1 ^( E0 k  H
  8. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |" ?% `. I0 J, t5 U3 s4 ]2 Q: E
  9.                (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码

//配置完后RCC->LLCFGR = 0x05403c19,然后对照寄存器RCC_PLLCFGR查看哪些位对应哪些功能
; n. u2 P# C4 ^1 Z$ i9 g& l//通过bit5~bit0可计算出PLLM=25,那么input VCO = PLL input clock /PLLM = 25M/25 = 1M,对应时钟结构图中的/M
/ p0 U5 j; z! R" O9 `7 x2 A//通过bit14~bit6可计算出倍频因子PLLN = 240,那么VCO output clock = PLLN * input VCO = 240 * 1 = 240M,对应时钟结构图中的xN
- [9 V" P' z$ Q9 Q9 j$ V  ^//bit17~bit16可计算出分频因子PLLP = 2,那么PLLCLK = VCO output clock /PLLP = 240/2 = 120M9 b! J& K  X8 k% [! m6 {
//bit22是选择给PLL输入的时钟源,输入时钟源有外部和内部高速时钟,这里选择的是外部高速时钟即PLL input clock = HSE =25M7 t1 ^1 `& u6 K1 B$ S) I( a
//bit27~24可计算出分频因子PLLQ = 5,那么PLL48CK = VCO output clock/PLLQ = 240/5 = 48M

  1. /* Enable the main PLL */
    & N- k' P" M$ x+ T4 i' Q
  2. RCC->CR |= RCC_CR_PLLON; //使能PLL! ]/ A0 }2 i7 C6 ^( D0 J4 f
  3. 8 j- `; i' e& x) w, m. ^3 ]
  4. /* Wait till the main PLL is ready */
    $ F6 x- v: |4 b( d
  5. while((RCC->CR & RCC_CR_PLLRDY) == 0)
    4 `' g: L* o0 Q3 [
  6. {
    2 q) ^$ K4 g2 j. V
  7. }
    . u" u8 e9 ^$ u) T( u  {
  8.     //到这里RCC->CR已配置完,最终值0x03036783- r0 I/ d" h6 e" l9 ]3 z7 N1 w
  9.     //通过查看用户手册知道,内部高速时钟、外部高速时钟、PLL时钟都已开启9 `9 T& Q% \) C! i
  10.    
    & `; q1 h! y& F4 {' Z. g
  11. /* Configure Flash prefetch, Instruction cache, Data cache and wait state */: X0 n% T! u  p0 Z; K3 g
  12. FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_3WS;5 i# k# e" y/ ~) ^
  13. % c- t) x% L4 `3 G  ~
  14. /* Select the main PLL as system clock source */
    & K' _7 o# \8 G( r9 a1 d  E: w
  15. RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));: P! p- G' ]3 \
  16. RCC->CFGR |= RCC_CFGR_SW_PLL;7 [, Y& W6 ?, |4 `9 P2 ^7 a  f
  17.    
    # n* Q! c2 K9 V% O6 f2 n. E
  18.     //到这里RCC->CFGR已配置完,最终值是0x0000_940A
    4 p# p: j' q' n9 ]" q* Z" z; `
  19.     //通过查看用户手册,知道,PLL时钟作为系统时钟即120M: Z6 r3 z  Q* G
  20.     //AHB不分频,即HCLK = 120M
    9 \# W& w5 n, ^) a- p2 r) `
  21.     //APB1 4分频,即fpclk1 = 120/4=30M
    4 D; ~/ a+ t6 h% r, P/ t
  22.     //APB2 2分频,即fpclk2 = 120/2=60M
    3 L) l0 N  a1 b& d/ i( F
  23. ; f* t5 z5 g. G% D
  24. /* Wait till the main PLL is used as system clock source */3 a: ~2 g; D% P8 e# l
  25. while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);3 t5 O5 _% C- V* |$ l! |+ ^1 L6 _
  26. {2 R  m  D# A) N: u( v( k& p. w+ |
  27. }
复制代码

}
3 z% C4 k# U( G" U' E" B( jelse2 B7 e* W2 M9 k0 f9 J
{ /* If HSE fails to start-up, the application will have wrong clock
) S7 W' s0 O3 z( Aconfiguration. User can add here some code to deal with this error */7 j$ {" E$ g  V) ~1 R
}

}; s% G+ Q3 r) v& Q  k

4 c$ m, y7 f3 J% k; A# F0 P+ ]% e

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

总结:

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

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

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


; i9 k- d, |/ t, m: T8 j
收藏 评论0 发布时间:2021-12-3 16:00

举报

0个回答

所属标签

相似技术帖

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