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

基于STM32时钟系统经验分享

[复制链接]
攻城狮Melo 发布时间:2023-11-4 19:02
1 STM32的时钟源主要有:& W4 z. y* ^. t* X7 M' g1 W6 Q
内部时钟0 l6 e7 K# g  V3 M. u$ }" u$ g
外部时钟
9 P: W7 \/ a! M2 C锁相环倍频输出时钟
! Y% O7 c5 m6 o' B1 L
微信图片_20231104190126.png

. J$ K& r; N+ v: [2 ~) i5 E3 O$ p' z: Q3 E
1.1 详细介绍
$ M# }  W4 ?7 x( O- x& ^
HSI(内部高速时钟)
, V% P4 l) l1 a& Y  [它是RC振荡器,频率可以达到8MHZ,可作为系统时钟和PLL锁相环的输入" Z) U" |4 O* Q3 z
& p, c/ p& e8 W* |
HSE(外部高速时钟)
  k, }3 M! U! J) R/ h5 U& o接入晶振范围是4-16MHZ,可作为系统时钟和PLL锁相环的输入,还可以经过128分频之后输入给RTC。% E4 Q- _0 @9 m! ^6 N* B) t

" a3 N# I( }# a; G
LSI(内部低速时钟)
) M, e" o" Y* L, c4 u它是RC振荡器,频率大概为40KHZ,供给独立看门狗或者RTC,并且独立看门口只能依靠LSI作为时钟源
' M. R9 Y) w2 c  R! X  \2 E9 G! o0 ]3 k3 ~
LSE(外部低速时钟)5 z- j* L5 z2 `: T
通常外接32.768MHZ晶振提供给RTC2 s, ]- T* Y3 Z" k# y

, ]0 i& L- S& Z. c3 E
PLL(锁相环)
% q' m- z9 c- g8 \* c+ B4 y用来倍频输出。因为开发板外部晶振只有8MHZ,而STM32最大工作频率是72MHZ。他可以通过HSI输入,HSE输入或两分频输入,通过PLL倍频(2-16),倍频之后输入给系统时钟。
; P8 I, V  [: b9 K& Z
* K9 l4 ]5 ]# b5 n% {
MCO(时钟输出管脚)
1 Z8 j2 ?6 O7 H. _- i通常对应STM32 PA8,它可以选择一个时钟信号输出,给外部的系统提供时钟源2 ^% }/ F7 l- D4 e/ Y* G9 {+ W

# ]) K0 ?4 H. m* [3 @' A: R
2 标准库的时钟配置& Y. t/ w8 D# y! R2 F- \) n4 R
2.1 STM32启动文件

- Y3 v1 K) E8 h* ]  w首先打开startup_stm32f10x_hd.s,该文件为stm32的启动文件,在该文件内会发现有这么一块用汇编写的代码。
2 W. x/ c$ `* c* g( T
  1.       Reset_Handler   PROC" Q) C* a( V  R
  2.             EXPORT  Reset_Handler    [WEAK]
    + ?; X4 H3 y. Q  L* y) f- C/ M
  3.             IMPORT  __main
    3 Y) n$ H" J& c1 `. {( {
  4.             IMPORT  SystemInit
    # ^% b- r; c; M& K6 \4 b& h
  5.             LDR     R0, =SystemInit
    , D4 w  M+ @5 d3 O0 u( o
  6.             BLX     R0               
    3 l* G# b* k* b6 l
  7.             LDR     R0, =__main
    # F% Q, I$ D  y# R1 v2 N
  8.             BX      R0
    3 c+ \5 s# E+ r. K' U
  9.             ENDP
复制代码
+ i7 X+ ~, L. s3 i; ~9 h# ^
通过这段汇编代码可以看出,程序在执行main函数之前,会先执行SystemInit函数。
( |! g1 y8 J: k7 H
5 n( S/ B& c- d$ S- s8 Z2 B3 G
2.2 SystemInit函数详解
  1. void SystemInit (void)
    , [: k+ q% f' Z1 n) w
  2. {
    $ w. T5 Y  G. K% P  p
  3.   /* Reset the RCC clock configuration to the default reset state(for debug purpose) */" o$ q8 ?7 I! j, r
  4.   /* Set HSION bit */
    6 y5 N0 U+ X; D
  5.   RCC->CR |= (uint32_t)0x00000001;3 M* n) E/ \1 M, O, D  J8 ?3 I& d

  6. " N0 P1 O/ e9 i* }
  7.   /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */8 D3 [7 x$ o- u+ s$ k4 i6 n
  8. #ifndef STM32F10X_CL
    ! Z  E( X2 ^# d6 ?# L9 t7 d  J
  9.   RCC->CFGR &= (uint32_t)0xF8FF0000;
    2 V0 B7 O+ B8 v6 Q  L$ E* F5 p
  10. #else
    3 d* e+ G# V* I9 Q9 q
  11.   RCC->CFGR &= (uint32_t)0xF0FF0000;+ i2 n; g: i8 b& L! M! T
  12. #endif /* STM32F10X_CL */   
    , _0 L  X- K8 h  l
  13. - e2 [1 y) b1 s* I6 e
  14.   /* Reset HSEON, CSSON and PLLON bits */0 i9 Y$ l* R) A0 h) Z5 s! y5 \
  15.   RCC->CR &= (uint32_t)0xFEF6FFFF;
    $ j4 X* z. G/ m9 r. @
  16. / z( p7 t% H! ~1 A4 t+ u  t
  17.   /* Reset HSEBYP bit */
    ; |3 _2 L$ i+ R4 I
  18.   RCC->CR &= (uint32_t)0xFFFBFFFF;
    ' b% n( D% E/ Z0 Y- z. B" ~9 y

  19. % {# L8 U& y. ~, w
  20.   /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
    2 g9 g- R0 @; R( }/ u% F7 }2 i* M
  21.   RCC->CFGR &= (uint32_t)0xFF80FFFF;3 Q% x! Q# x* v+ e) c3 ^  _
  22. " p2 N8 _2 @+ r! `( T
  23. #ifdef STM32F10X_CL
    1 H6 v( A. u* V2 Z/ M6 @
  24.   /* Reset PLL2ON and PLL3ON bits */
    7 V; K# s0 h. n+ \  F2 O
  25.   RCC->CR &= (uint32_t)0xEBFFFFFF;) Q/ D- r. Q! `1 y" l& }2 k
  26. # [  ?& \: o) W: X' j- V1 @6 |4 U2 K
  27.   /* Disable all interrupts and clear pending bits  */1 F7 q# p& N; X3 x) y9 W
  28.   RCC->CIR = 0x00FF0000;
    + o  [6 m! n4 ~& [4 V6 ?4 a

  29. + F# z$ B# g8 K- B/ K
  30.   /* Reset CFGR2 register */
    8 B) x* M- j6 j4 B
  31.   RCC->CFGR2 = 0x00000000;
    7 Q0 i3 `% {4 B7 a) \
  32. #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL). O  g; D& y4 G) `/ p* e
  33.   /* Disable all interrupts and clear pending bits  */
    * N9 {6 e  t) |$ l* V
  34.   RCC->CIR = 0x009F0000;6 o3 I/ t/ [( B/ P1 b
  35. " x2 F! k( X5 B  t
  36.   /* Reset CFGR2 register */
    6 t0 F$ B6 Z8 h" Y+ p
  37.   RCC->CFGR2 = 0x00000000;      $ p% A# t. c1 {. d& [/ a
  38. #else+ _- }5 ^* n0 U& H( n
  39.   /* Disable all interrupts and clear pending bits  */; f& n: X7 j1 c# Y' D
  40.   RCC->CIR = 0x009F0000;
    ; n& R- W8 `( t9 m' X
  41. #endif /* STM32F10X_CL */
    $ J2 E( c$ d/ H; c

  42. 2 B7 R: O( a2 L" N$ \
  43. #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
    8 a; @+ E( x1 S$ p
  44.   #ifdef DATA_IN_ExtSRAM. `3 V* k5 [5 n5 |. A7 m1 {
  45.     SystemInit_ExtMemCtl(); , d1 w- J3 ?4 T
  46.   #endif /* DATA_IN_ExtSRAM */: T3 |* D$ G8 g0 T6 H) D, X0 x
  47. #endif
    ! @. A" B0 H: x* B' F

  48. 6 V) T+ M$ a9 k: @" ^
  49.   /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
    / F* o& e. ^+ l+ d
  50.   /* Configure the Flash Latency cycles and enable prefetch buffer */( c# l' F4 _7 h1 h8 }
  51.   SetSysClock();
    / ~+ X4 B. _& H) c3 ~2 Y) S  A. }
  52. 0 G4 N/ M' w% R4 J. _
  53. #ifdef VECT_TAB_SRAM
    3 {" ~6 b% J- S6 N
  54.   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
    ! U3 d5 k$ F. e6 k3 w* u5 |
  55. #else- H, L. i: a" r6 y; ^- a
  56.   SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
    9 V' q6 T: f5 P* w/ B8 |& }
  57. #endif
    $ G/ O# ]# g+ l% F! i% c' I1 o
  58. }
复制代码
& @3 f& @# r5 Z. u
3 K$ p( n/ P( l( U" v
打开内部8M时钟:) J, ~# K/ ?0 e! i# @2 h
  1. RCC->CR |= (uint32_t)0x00000001
复制代码
9 D8 |1 F) M4 u5 R, B  h+ N
通过查看寄存器手册可知,这段代码为打开内部8M时钟。- Q) l8 W1 b) p+ x( |

, z- r( o% c& L4 ]
微信图片_20231104190120.png
$ Q4 s/ h4 y4 H1 [% I& Y5 v  f9 v- {
! _0 A: l/ h2 o! y/ j
设置时钟配置寄存器:
) ^& K$ v* ?& u0 a( z& k/ o& z
  1. #ifndef STM32F10X_CL
    : X5 Y4 J2 B3 l' n
  2.   RCC->CFGR &= (uint32_t)0xF8FF0000;
    4 I" i) a6 g4 e9 n, v( U! b, ~
  3. #else3 X; x! R- v* k6 p  Z& y) l5 j( c' ?
  4.   RCC->CFGR &= (uint32_t)0xF0FF0000;$ z1 R  o8 ^# f- E* ]- C0 w
  5. #endif /* STM32F10X_CL */   
复制代码

7 A# J* q7 n7 Z/ g. F5 m5 H对应寄存器说明可查看《STM32中文参考手册_V10》的6.3.2 时钟配置寄存器(RCC_CFGR)章节。
( Q* T4 `: r" I/ `% n6 ?后续代码,有兴趣可根据《STM32中文参考手册_V10》手册,查看代码具体作用。
2 ]' {: ]. c' E1 O. R5 i, `
$ f+ Q$ \$ l/ m3 v7 C
2.3 SetSysClock()函数详解9 E# s1 g2 M) z* b$ S# G& g
  1. static void SetSysClock(void)( _% {' L* l% E9 A, d, Z$ k
  2. {9 `6 ?% w) U) ?- t0 S0 u
  3. #ifdef SYSCLK_FREQ_HSE3 x/ J% n* R/ O9 v+ t
  4.   SetSysClockToHSE();
    3 ?! \2 `1 `% @3 {2 b/ H
  5. #elif defined SYSCLK_FREQ_24MHz
    ; v% ~6 v; T4 ], w! l0 X8 C
  6.   SetSysClockTo24();
    5 l6 p7 F! M9 L8 B; A0 s9 D" Y8 T" N* W
  7. #elif defined SYSCLK_FREQ_36MHz/ }- T, L5 ~3 n: w3 |
  8.   SetSysClockTo36();" P2 d" G+ k5 H% ]* r
  9. #elif defined SYSCLK_FREQ_48MHz
    ; L. Q% M1 {' p, L2 `% c+ M  R" f  Z2 Z
  10.   SetSysClockTo48();
    4 T4 y" `- e) t! o8 c" D
  11. #elif defined SYSCLK_FREQ_56MHz
    # {3 v$ H8 T- Q
  12.   SetSysClockTo56();  
    0 `# r' `! H2 }2 ^* v
  13. #elif defined SYSCLK_FREQ_72MHz
    9 x" h: ~& G# z: V6 ?- p
  14.   SetSysClockTo72();$ d4 w$ l7 p7 v: o* [* |- }9 ?, n
  15. #endif
    6 p& P5 m8 M; v0 X( B, [$ Z
  16. }
复制代码
% y: u  R7 h' Y, j# B
! j- [# s- s7 u% {: g$ Y
system_stm32f10x.c文件中会根据芯片的型号定义对应的宏:% j- G, E/ i3 d, P7 V, \9 O
  1. #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
    ( I1 X, w$ k1 V4 P' F" x
  2. /* #define SYSCLK_FREQ_HSE    HSE_VALUE */# F# `2 N4 s2 K$ _' z( E/ a' m6 L
  3. #define SYSCLK_FREQ_24MHz  240000009 m  ]) W; J; A" E. |8 F6 o
  4. #else3 P1 o- w  s$ S
  5. /* #define SYSCLK_FREQ_HSE    HSE_VALUE */# i" Z1 ~8 p! W. J+ N/ u
  6. /* #define SYSCLK_FREQ_24MHz  24000000 */ % P! K5 g, ]' G8 S& i
  7. /* #define SYSCLK_FREQ_36MHz  36000000 */8 y/ T  j1 }6 ?6 j/ _. o3 H" J
  8. /* #define SYSCLK_FREQ_48MHz  48000000 */4 H4 ~. ?" R' a, ?
  9. /* #define SYSCLK_FREQ_56MHz  56000000 */
    " J" z/ D, r/ V0 E! W1 ^1 a7 J
  10. #define SYSCLK_FREQ_72MHz  72000000
    " S3 h2 v2 ~; t
  11. #endif
复制代码
% @7 C* i1 o7 ~6 ]8 T5 f, M2 D
3 时钟配置函数: A: d. s: \+ Y* G+ Q
3.1 时钟初始化配置函数
  1. void SystemInit(void);
    7 O- _( O  B0 p& f. s
  2. SYSCLK(系统时钟)=72MHZ;" O1 \9 y( G" p4 Q! U9 t
  3. AHB总线时钟(HCLK=SYSCLK)=72MHZ;
    3 h  @5 P/ P- j/ X- L$ q
  4. APB1总线时钟(PCLK1=SYSCLK/2)=36MHZ;# [4 T- Z; _1 A  t# m& {6 `
  5. APB2总线时钟(PCLK1=SYSCLK/1)=72MHZ;
    * u! B! N  o. D" Z" G/ ]7 J
  6. PLL主时钟=72MHZ;
复制代码
0 n$ N9 Z  J% U; G5 ]& z/ Y$ x: s
* ^+ N# n; W$ U* B  o1 @
3.2 外设时钟使能配置函数
3 F9 f4 T0 ?" J: z, U, }5 p
  1. void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
    * j- f# y. l) H
  2. void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);* r: {, n/ R1 V
  3. void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
复制代码
. m+ C5 R9 [, U7 K! i) B  X
3.3 时钟源使能函数
  1. void RCC_HSICmd(FunctionalState NewState);
    : G4 T$ T8 w9 ~2 ]2 d
  2. void RCC_LSICmd(FunctionalState NewState);9 N3 T( |2 d3 x* D( v7 v; B, h
  3. void RCC_PLLCmd(FunctionalState NewState);
    ) K; I$ v7 O  v! w, i2 n
  4. void RCC_RTCCLKCmd(FunctionalState NewState);
复制代码
% }0 `9 k* C+ L! {" q6 C9 y
0 W8 }+ B' @2 ?7 ~; p# b
3.4 时钟源和倍频因子配置函数
( v; d7 ^( f2 C: A, i, V; i+ Y: x
  1. void RCC_HSEConfig(uint32_t RCC_HSE);* B4 k* W" r7 L0 k
  2. void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);
    5 k) @" G5 J$ B) K( T% e
  3. void RCC_HCLKConfig(uint32_t RCC_SYSCLK);7 y2 ^# {: y1 [/ V# T
  4. void RCC_PCLK1Config(uint32_t RCC_HCLK);
    ; Z. h  `2 w  a& n
  5. void RCC_PCLK2Config(uint32_t RCC_HCLK);
复制代码
( N) ~' U; }0 A" N! x) w
3.5 外设时钟复位函数+ T% ~& ]7 b, l; G: }% H
  1. void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
    8 ], Q& l! o9 r* j
  2. void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
复制代码

8 v! ~3 o1 V! f+ o& Y3.6 自定义系统时钟. ?6 a5 ]0 ~: \3 `
  1. void RCC_HSE_Config(u32 div,u32 pllm)
    9 u# L( l6 `! g, ]) E* P2 y, i0 r
  2. {
    # k0 t: A! Y1 Q! v7 ]' R
  3.     RCC_DeInit();, o* A& z8 a3 L6 u
  4.     RCC_HSEConfig(RCC_HSE_ON);
    ; n$ D; R4 Y/ V6 k* |5 v; O
  5.     if(RCC_WaitForHSEStartUp()==SUCCESS)/ l' G" f3 r& Y; o) a8 ^, p
  6.     {   5 t! l/ U# i; j4 s
  7.         RCC_HCLKConfig(RCC_SYSCLK_Div1);
    . o$ }& m0 k  f# T' P
  8.         RCC_PCLK1Config(RCC_HCLK_Div2);8 t" \1 E  J7 d% e7 z& }
  9.         RCC_PCLK2Config(RCC_HCLK_Div1);* E! q0 w- d+ T8 ^0 H; s8 N
  10.         RCC_PLLConfig(div,pllm);
    8 J# y+ q) L+ E$ \+ R
  11.         RCC_PLLCmd(ENABLE);     - x4 S, }9 W( c' M5 G# k8 n
  12.     while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)
    ' c" F! S0 g. v4 `* i- H
  13.         RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK)
    : ^4 k& r/ N& |. u! \& ^+ k
  14.     while(RCC_GetSCLKSource()!=0x08);
    ( ~0 {5 m3 U6 x) u) [, K5 F

  15. * Y4 w0 f  ]( n
  16.     }
    / E& M+ Y0 Q0 L- A
  17. }
复制代码
转载自:STM32嵌入式开发7 j1 {1 n& ^8 w
0 c" U+ S7 Z0 H: o9 A
如有侵权请联系删除& [3 {3 Y( B, n% X, S
% v; D- J5 C; ^! u6 N, x
收藏 评论0 发布时间:2023-11-4 19:02

举报

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