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

【经验分享】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 handler3 F' g* D" m" l9 u; R  H
  2. Reset_Handler PROC' J, D7 E$ L+ z
  3. EXPORT Reset_Handler [WEAK]
    2 C$ @* m) d" M
  4. IMPORT SystemInit
    ! a* _8 x, S% @# A4 v0 d
  5. IMPORT __main$ j7 z- {( t( n7 F- \
  6. LDR R0, =SystemInit
    , a0 b! J- C/ d1 f0 j+ S& Q
  7. BLX R0
    + z6 r: B$ W7 }. h# c
  8. LDR R0, =__main
    9 W' m, p: ^5 Y- W, U2 {0 }" A
  9. BX R0: o- y  K$ @$ j% y; e
  10. ENDP</font>
复制代码

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

  1. <p style="line-height: 26px;"><font face="-apple-system, " "=""><font style="font-size: 16px" color="#000000">void SystemInit(void)6 f/ f( X  G7 x
  2. {
    # F( W( _; R/ J
  3. /* Reset the RCC clock configuration to the default reset state ------------<i>/
    2 L/ k) F% Q9 [4 c; {
  4. /</i> Set HSION bit */
    ' u! ~5 y" b( j( \) Y5 C
  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 */
    . I; T' [. F$ U! [5 d/ `" b* J* l8 u
  6. RCC->CFGR = 0x00000000; //通过开关SW选择内部高速时钟作为系统时钟16MHZ: w6 Q+ \" [( m0 P; T3 x
  7. //AHB prescaler 不分频8 \6 {( n  R& J! T- c
  8. //APB Low speed prescaler (APB1) 不分频,fplck1 = 16MHZ6 R" {  C9 v3 S( W+ X
  9. //APB high-speed prescaler (APB2)不分频,fplck2 = 16MHZ/ e4 p$ Q+ A. k
  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 */
      w; N, l5 r, y3 v. q
  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 */
    7 a! f# {8 N. D/ 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 */
    ) ^8 \. J2 p3 m3 U7 X  J, L9 Q% T9 O
  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 */7 T- `7 _9 p6 Q  j
  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# k3 s/ {! Z4 }& ~. V
  15. SystemInit_ExtMemCtl();
    $ R- x% {/ v/ s4 u( 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,
    " z% _2 Y4 S2 O
  17. AHB/APBx prescalers and Flash settings ----------------------------------*/: o. f  [# X7 \* y0 X
  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>/
    * B, a, A# \5 z
  19. #ifdef VECT_TAB_SRAM" J8 W& ~' g7 r- V7 @; P
  20. SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /</i> Vector Table Relocation in Internal SRAM <i>/$ X, _+ V& k% N. z$ k( F! I
  21. #else1 b1 U: p; E2 F- }
  22. SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /</i> Vector Table Relocation in Internal FLASH */1 F. V* a$ V8 Z( o  \
  23. #endif4 v1 I0 h# M8 d; s$ n8 K7 C- o
  24. }</font></font></p>
复制代码

  Z( J$ p. i7 {. V" q& ?7 \

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

) b0 u: o4 n- f* }9 Y
static void SetSysClock(void)
: Z: k- u1 S7 c) Q: q9 o{
! g: W! g7 ?: T) P/*****************************************************************************/1 \0 ?3 g: n7 f$ W6 q; r
/
PLL (clocked by HSE) used as System clock source /# {$ I/ c" R. O7 T, w* N
/
*****************************************************************************/
5 W6 U; {* _  m+ j$ s- S__IO uint32_t StartUpCounter = 0, HSEStatus = 0;

/* Enable HSE */
6 h  {! V% d$ l0 _6 CRCC->CR |= ((uint32_t)RCC_CR_HSEON); //外部高速时钟使能,25MHZ

/* Wait till HSE is ready and if Time out is reached exit */ //外部时钟使能后,得需要一点时间到达各个端口
, i- I/ L. A% ido
- A( _. B. ^7 ]  s/ ^7 m4 h{3 D7 V3 J/ X6 N' m! W) \9 d
HSEStatus = RCC->CR & RCC_CR_HSERDY; //如果RCC_CR_HSERDY为0,说明外部时钟还没准备好,1说明外部时钟已准备好
: g! D5 E: Z7 q' ^- z  s) ^! R% HStartUpCounter++;//对读的次数进行累加,当累加次数到达1280次时,就意味着启动时间超时
  a3 A  U3 l; w) }! I  k6 `} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

if ((RCC->CR & RCC_CR_HSERDY) != RESET)//这里判断上面的do while循环是因哪个条件结束的1 o% a4 l/ o' E! T2 a1 }! b3 y* M
{/ ]6 G# ^' B, N" x  a4 L- [$ g' m
HSEStatus = (uint32_t)0x01; //说明时钟已准备好了,才结束do whlie循环' y2 X$ J8 z1 w/ {
}; P. o# S6 @: q6 l# A4 f
else
' x0 i( B8 ~" [3 i" K: s{
4 b; N4 f* ^1 S$ G' QHSEStatus = (uint32_t)0x00; //说明是因为超时了而退出do while循环1 J- l. G, o0 o1 ~* G9 `
}

if (HSEStatus == (uint32_t)0x01)
* l/ \) ~. s' O. D  \6 U/ S{
7 g- N! x" F, c* a  o, D/* HCLK = SYSCLK / 1*/! ]  q* Z- @# S( Z4 K$ M" Z
RCC->CFGR |= RCC_CFGR_HPRE_DIV1; //AHB不分频,AHB出来后时钟就是sysclk=120M

  1. /* PCLK2 = HCLK / 2*/
    * V& n$ W/ A" e: \2 U. M
  2. RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;//APB2 2分频,fpclk2 = sysclk/2 = 60M1 ], _1 a# b: p. E' J6 e, A4 c

  3. 9 I1 }4 F2 {, j( M
  4. /* PCLK1 = HCLK / 4*/1 }5 k3 P$ c, [
  5. RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; //APB1 4分频,fplck1 = sysclk/4 = 30M
    ) u0 S0 f+ Q; O( l
  6. 4 K+ w- G* H, O+ Y4 x, p4 S
  7. /* Configure the main PLL */ //主要对PLL和PPI2S 进行配置% C" N* p/ J5 ~
  8. RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |8 U( V1 \5 N; I! y2 `
  9.                (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
复制代码

//配置完后RCC->LLCFGR = 0x05403c19,然后对照寄存器RCC_PLLCFGR查看哪些位对应哪些功能
8 [+ D' M6 P+ ~8 w/ P* ]9 ^//通过bit5~bit0可计算出PLLM=25,那么input VCO = PLL input clock /PLLM = 25M/25 = 1M,对应时钟结构图中的/M& ]5 D; Q) [/ _, `: P4 R1 L1 L, W/ g
//通过bit14~bit6可计算出倍频因子PLLN = 240,那么VCO output clock = PLLN * input VCO = 240 * 1 = 240M,对应时钟结构图中的xN
8 v# f1 m. j- Q" B4 D- i& J//bit17~bit16可计算出分频因子PLLP = 2,那么PLLCLK = VCO output clock /PLLP = 240/2 = 120M8 m1 c  t4 m2 m/ ~. h: I) B
//bit22是选择给PLL输入的时钟源,输入时钟源有外部和内部高速时钟,这里选择的是外部高速时钟即PLL input clock = HSE =25M
8 C+ g0 L: \# e5 u. O' r//bit27~24可计算出分频因子PLLQ = 5,那么PLL48CK = VCO output clock/PLLQ = 240/5 = 48M

  1. /* Enable the main PLL */
    3 B! ?; L4 W. o. H7 t" A/ e
  2. RCC->CR |= RCC_CR_PLLON; //使能PLL/ H2 ?* a& g$ `' c  P: S; o

  3. : E7 X' }. \; g  s* @
  4. /* Wait till the main PLL is ready */
    % t- x9 q: i1 {) e/ V5 u5 Y. m8 K
  5. while((RCC->CR & RCC_CR_PLLRDY) == 0)  F$ R- I( c! P( e( U& O
  6. {
    " B- e% s, D, e6 n
  7. }
    5 }0 ?- U; }; y$ v" ^
  8.     //到这里RCC->CR已配置完,最终值0x03036783
    ( t  p. E: Q9 e
  9.     //通过查看用户手册知道,内部高速时钟、外部高速时钟、PLL时钟都已开启0 y$ @3 j# d6 E4 o: s/ s9 P3 A2 ~
  10.    
    ( L, z# r' i6 ?  }3 k& o. q
  11. /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
    1 h! W6 _: p# c6 v9 j! C
  12. FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_3WS;' ?: G" g1 n) i) b! b) t4 p- p: r

  13. + d9 E% p3 e8 o3 I- B: @# n
  14. /* Select the main PLL as system clock source */3 T  d$ G5 O/ ^2 J- l( {
  15. RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));" u4 M$ z# G1 k5 A% j
  16. RCC->CFGR |= RCC_CFGR_SW_PLL;
    5 I; p3 |5 r5 M' `9 O- V- S
  17.     7 U( r9 r3 R0 f4 o
  18.     //到这里RCC->CFGR已配置完,最终值是0x0000_940A9 k# W/ _: w% m& s: m- R; p
  19.     //通过查看用户手册,知道,PLL时钟作为系统时钟即120M' i1 U6 ^; \( u: n. e5 H# A% x
  20.     //AHB不分频,即HCLK = 120M
    6 ~8 z& r; k- u5 X8 f
  21.     //APB1 4分频,即fpclk1 = 120/4=30M
    * R  X' J; ?- W( J; F' P
  22.     //APB2 2分频,即fpclk2 = 120/2=60M
    . f) g: ~, j! p" S4 M. M
  23. # s' P3 z7 W& \( p4 M7 x
  24. /* Wait till the main PLL is used as system clock source */% I. b2 r; r6 P  _
  25. while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);! Y0 P# t; x, J3 U* l+ Q) n
  26. {7 k. t+ e  r4 y* c
  27. }
复制代码

}
6 r1 M+ ]& W; S# T& a6 E1 qelse! L0 U" B- T% V+ X' X& M  t
{ /* If HSE fails to start-up, the application will have wrong clock: S, c7 t; x9 M9 W
configuration. User can add here some code to deal with this error */
$ J% e8 S/ s2 X) a2 f2 h}

}- A( F! b  z- O( f3 Z+ z7 R5 u7 j& t
; m0 e- G7 |1 L! E9 _$ \

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

总结:

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

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

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

* k" `# U/ L) |' _* p
收藏 评论0 发布时间:2021-12-3 16:00

举报

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