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

【经验分享】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
    ( S2 h" |- z, \% ?! n$ f
  2. Reset_Handler PROC) h$ ]3 n& [) j
  3. EXPORT Reset_Handler [WEAK]
    * k# [1 W6 j+ l& w) h' H& k1 n; w* z
  4. IMPORT SystemInit2 ?6 Q9 J0 r* X  j& F& X. }* J
  5. IMPORT __main. ^7 ?5 T, |/ |* @) K4 I
  6. LDR R0, =SystemInit9 \6 i& {! ~" n( Q, Q- f% h* y
  7. BLX R0
    9 }# b) K, U9 J& B
  8. LDR R0, =__main
    6 ~, D+ E9 o0 D* l# ^
  9. BX R0) T7 P! M, ?3 E/ K7 Q! w
  10. ENDP</font>
复制代码

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

  1. <p style="line-height: 26px;"><font face="-apple-system, " "=""><font style="font-size: 16px" color="#000000">void SystemInit(void)1 V9 C& X* ]$ B  ?: Y  H$ H
  2. {
    5 @3 u! W# p5 y* x! k8 I
  3. /* Reset the RCC clock configuration to the default reset state ------------<i>/* n5 \" A# w6 u! A8 m
  4. /</i> Set HSION bit */5 {6 ?2 y5 s+ V* z
  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 */
    ' V! g5 S$ o6 q7 X
  6. RCC->CFGR = 0x00000000; //通过开关SW选择内部高速时钟作为系统时钟16MHZ! _: b6 |1 J6 ^6 y) V; `# ^
  7. //AHB prescaler 不分频2 a" {$ H4 U: Q) ^+ V2 n. V8 q
  8. //APB Low speed prescaler (APB1) 不分频,fplck1 = 16MHZ7 A4 o& G5 e3 B7 Q5 p
  9. //APB high-speed prescaler (APB2)不分频,fplck2 = 16MHZ$ ]: u; J8 C$ D: a/ G
  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 */% B8 z/ E9 F( }" w# n
  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 */8 J7 F& c- J4 v( i" q' w& D4 W) G" i
  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 */& @5 f' T9 G; T+ k4 r/ e
  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 */
    % u. I. |$ W; K  `) n
  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_ExtSRAM
    3 Y0 S- _! u7 D1 z! u
  15. SystemInit_ExtMemCtl();
    - {6 ]0 g; j( f7 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,
    5 `3 y0 c# B3 `' j7 K
  17. AHB/APBx prescalers and Flash settings ----------------------------------*/
    . z1 e  P% r* T1 x' V
  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>/) m3 T7 ]1 ?! p  P3 b
  19. #ifdef VECT_TAB_SRAM
      O  C  S9 Y8 B# [& F
  20. SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /</i> Vector Table Relocation in Internal SRAM <i>/
      g8 g8 _  H5 D2 {: @7 M( i
  21. #else- U/ ^6 N, K3 v. _& ?+ m
  22. SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /</i> Vector Table Relocation in Internal FLASH */
    2 h# z5 u& Y8 d$ b' {$ X
  23. #endif# c& b7 t; I  X5 A+ ~# U9 l
  24. }</font></font></p>
复制代码

0 x/ I" R5 q$ D- q

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


0 i; K2 S) v+ z4 dstatic void SetSysClock(void)
: H1 R2 Z* I3 {{
- C. N) M4 c7 j' X/*****************************************************************************/. }  F9 E  S8 Q  n
/
PLL (clocked by HSE) used as System clock source /' L3 v' Q( C1 t* O4 G: I
/
*****************************************************************************/
) [9 i' S4 v, |__IO uint32_t StartUpCounter = 0, HSEStatus = 0;

/* Enable HSE */
" j* q0 F. i8 X. L! IRCC->CR |= ((uint32_t)RCC_CR_HSEON); //外部高速时钟使能,25MHZ

/* Wait till HSE is ready and if Time out is reached exit */ //外部时钟使能后,得需要一点时间到达各个端口
2 b% O3 ?4 M; i0 Bdo
* z9 n( S7 k) S; t. C{
1 Q( V! j, t9 RHSEStatus = RCC->CR & RCC_CR_HSERDY; //如果RCC_CR_HSERDY为0,说明外部时钟还没准备好,1说明外部时钟已准备好+ F0 u* P: o. o+ M
StartUpCounter++;//对读的次数进行累加,当累加次数到达1280次时,就意味着启动时间超时
  G+ _' [$ }, i1 y} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

if ((RCC->CR & RCC_CR_HSERDY) != RESET)//这里判断上面的do while循环是因哪个条件结束的
; J) C2 N6 A8 L0 D{
( G" z& e* Q9 z+ Q, e: M" }! t5 ?HSEStatus = (uint32_t)0x01; //说明时钟已准备好了,才结束do whlie循环) n' O/ L4 p0 Z- X* k0 d, A2 f6 G2 ~
}
4 u8 ?$ g- J' Z0 f! ?( ^8 Y+ w2 Helse+ _) \+ f* W  J* L9 V
{
) E; _' _) f, v, LHSEStatus = (uint32_t)0x00; //说明是因为超时了而退出do while循环
2 e: X& W8 S" a" I( g}

if (HSEStatus == (uint32_t)0x01)
) F& O( |- e4 ?{
( P: C1 m! i9 H+ `7 \! e  u$ R, S4 c% d: d/* HCLK = SYSCLK / 1*/- h0 e+ g% J# G5 ^$ T7 O, w# J
RCC->CFGR |= RCC_CFGR_HPRE_DIV1; //AHB不分频,AHB出来后时钟就是sysclk=120M

  1. /* PCLK2 = HCLK / 2*/5 E2 m3 ?2 r5 W6 j# P0 p
  2. RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;//APB2 2分频,fpclk2 = sysclk/2 = 60M
    3 Z3 e2 Z7 J3 ?" z$ r$ M$ x, R
  3. " I! ?, t+ b9 s, t9 p8 ~0 Q
  4. /* PCLK1 = HCLK / 4*/
    % N7 f& a9 O! p, ]% k0 _
  5. RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; //APB1 4分频,fplck1 = sysclk/4 = 30M
    . h+ f- o2 ?7 T& o1 P3 ^# x/ n, t
  6. , ^. d! H. _9 r: \
  7. /* Configure the main PLL */ //主要对PLL和PPI2S 进行配置
    0 m! v2 }! U2 z) b& ^# v
  8. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |0 A$ v# L: i7 G$ O7 }# c
  9.                (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码

//配置完后RCC->LLCFGR = 0x05403c19,然后对照寄存器RCC_PLLCFGR查看哪些位对应哪些功能
% g; Z( a, S0 ^//通过bit5~bit0可计算出PLLM=25,那么input VCO = PLL input clock /PLLM = 25M/25 = 1M,对应时钟结构图中的/M- P4 `' O5 i  @! S. W' m$ x3 F
//通过bit14~bit6可计算出倍频因子PLLN = 240,那么VCO output clock = PLLN * input VCO = 240 * 1 = 240M,对应时钟结构图中的xN
' U0 ~' ~' W! t  J" W//bit17~bit16可计算出分频因子PLLP = 2,那么PLLCLK = VCO output clock /PLLP = 240/2 = 120M
1 q9 c2 I% r6 p5 v2 \6 V# f# T: U//bit22是选择给PLL输入的时钟源,输入时钟源有外部和内部高速时钟,这里选择的是外部高速时钟即PLL input clock = HSE =25M
6 M% H/ \" W8 L- _- g  ^//bit27~24可计算出分频因子PLLQ = 5,那么PLL48CK = VCO output clock/PLLQ = 240/5 = 48M

  1. /* Enable the main PLL */
    : e) x, k$ M- a: w' [" g
  2. RCC->CR |= RCC_CR_PLLON; //使能PLL
    ( T9 l9 [8 v! T  R- T

  3. ) t8 \: z$ q7 ]) G. d  I$ k! N
  4. /* Wait till the main PLL is ready */" ?/ ?8 k% ~) \' l1 G9 g, @2 P
  5. while((RCC->CR & RCC_CR_PLLRDY) == 0)' c  X2 k2 i7 L, O- X+ ?9 Q
  6. {
    ; s; j+ k" ^6 }6 z  }4 z+ L
  7. }
    * O, h9 X' C6 }4 G6 x) T% }, K  O# {
  8.     //到这里RCC->CR已配置完,最终值0x03036783+ W0 ^) C  D) P& s8 i9 m0 }
  9.     //通过查看用户手册知道,内部高速时钟、外部高速时钟、PLL时钟都已开启
    , A& V/ V* C+ C, L) ?
  10.    
    ! I! V5 N8 f4 }
  11. /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
    % |  S' e, ^8 Z) X  H
  12. FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_3WS;
    * U' m3 o; y. j$ E% x, J1 L

  13. - l* ]+ P1 ?/ s, s  z$ h3 q
  14. /* Select the main PLL as system clock source */8 i; H/ R# ^" O; }) f% ^+ {" T
  15. RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));& Y$ m" L2 L' ~4 |% O: d' _( U2 k! c
  16. RCC->CFGR |= RCC_CFGR_SW_PLL;
    2 J7 Y# }1 V8 D" D2 H5 \* ]% K% R2 e* f
  17.    
    * ?( X% ~5 l& \
  18.     //到这里RCC->CFGR已配置完,最终值是0x0000_940A
    4 ?' `# }$ H8 o; D8 T
  19.     //通过查看用户手册,知道,PLL时钟作为系统时钟即120M
    , d5 m0 D$ K* n
  20.     //AHB不分频,即HCLK = 120M2 ]. x9 n1 d$ y- _
  21.     //APB1 4分频,即fpclk1 = 120/4=30M6 |( j4 d5 C: Y/ m
  22.     //APB2 2分频,即fpclk2 = 120/2=60M
    ; k- F$ T2 o5 w1 [
  23. ( B' k8 `5 X& T: p5 X
  24. /* Wait till the main PLL is used as system clock source */  q) `( ?% L1 j: Y( ~' N
  25. while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
    . ?5 b; ~& c" R/ B' F8 {6 {: x: M" {
  26. {5 n, {8 T: s- }- F% [
  27. }
复制代码

}
/ L- K; B2 T' G, s% H1 gelse+ \# q9 P* H3 @/ a% S* X7 p
{ /* If HSE fails to start-up, the application will have wrong clock
0 o0 n$ R- ?3 `- G; T6 _configuration. User can add here some code to deal with this error */
" J$ j- b* z5 T( J" p2 E! f- w}

}' O" k$ C! G+ s. g5 p) Y7 \0 O- w

' j: B( g/ X9 \  T3 A

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

总结:

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

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

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

2 b( J8 \# W: e# V
赞 收藏 评论0 发布时间:2021-12-3 16:00

举报

0个回答

所属标签

相似技术帖

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版