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

基于STM32时钟系统经验分享

[复制链接]
攻城狮Melo 发布时间:2023-11-4 19:02
1 STM32的时钟源主要有:
6 u0 F' v. r" R4 H; B' D内部时钟* P, }) H) N+ |8 V( s0 Y" z* T
外部时钟
8 m5 g& d1 y7 w" G7 |锁相环倍频输出时钟
2 f; K! H/ N; G1 t
微信图片_20231104190126.png

4 ~! Z8 r( d* o
1 b* w2 t' _6 `1.1 详细介绍

  e) @1 _" @+ I0 t' a5 [$ GHSI(内部高速时钟); x+ y4 G& `1 _6 s* z. n
它是RC振荡器,频率可以达到8MHZ,可作为系统时钟和PLL锁相环的输入$ [5 z8 j: y% P3 o5 x9 P
* \9 W* T0 N9 a4 v  b
HSE(外部高速时钟)% {, A1 u0 `' j) s
接入晶振范围是4-16MHZ,可作为系统时钟和PLL锁相环的输入,还可以经过128分频之后输入给RTC。( y8 B" V( C7 \& O4 t* I
8 |  D# t/ z% w9 T6 I& z8 i
LSI(内部低速时钟)% t5 ?: S1 O" C' E4 y
它是RC振荡器,频率大概为40KHZ,供给独立看门狗或者RTC,并且独立看门口只能依靠LSI作为时钟源
2 c9 B$ I+ V8 @- W" ~
# r, Z& U: u2 Q# ~0 ]1 Z3 K: \3 ?
LSE(外部低速时钟)
* x! E" V. W' X. F, ]$ ]! p/ S通常外接32.768MHZ晶振提供给RTC* J$ p/ Y* P- T) P" W
! Q. N$ j2 A+ C4 a
PLL(锁相环)+ y) J. ]- d. u8 f* k+ ?
用来倍频输出。因为开发板外部晶振只有8MHZ,而STM32最大工作频率是72MHZ。他可以通过HSI输入,HSE输入或两分频输入,通过PLL倍频(2-16),倍频之后输入给系统时钟。& `- {1 h+ V$ s) P7 n6 ]
" [# N5 r. u9 n9 I7 x3 m+ K
MCO(时钟输出管脚)+ t4 I9 ^/ q5 u/ f0 K9 B; Q. t
通常对应STM32 PA8,它可以选择一个时钟信号输出,给外部的系统提供时钟源
' i( g3 L6 x9 j+ P4 E* }
0 I1 \; \# {5 O) `
2 标准库的时钟配置# z2 K& h7 }; u9 D. b
2.1 STM32启动文件

& n# L  E8 }9 b$ V6 R/ c9 ^首先打开startup_stm32f10x_hd.s,该文件为stm32的启动文件,在该文件内会发现有这么一块用汇编写的代码。
# @$ h% i. a+ u3 T; `* c1 [
  1.       Reset_Handler   PROC& ^) |* h6 ?! [+ x: i) n
  2.             EXPORT  Reset_Handler    [WEAK]
    8 |. ?" n. `3 z4 k3 l8 G
  3.             IMPORT  __main
    - f8 m, l* p) q, h+ J
  4.             IMPORT  SystemInit3 I8 B5 s2 ^4 [7 c9 U
  5.             LDR     R0, =SystemInit
    ! m9 {' F( @; B( {- a5 F
  6.             BLX     R0               
    ! Y" w7 v# @) @. Q2 {2 g* b
  7.             LDR     R0, =__main
    7 a, g: r) K( m
  8.             BX      R0) a0 l0 {4 a+ F& K0 Z" c: n6 m
  9.             ENDP
复制代码
5 H5 `1 F8 ~2 u- ~7 z8 T
通过这段汇编代码可以看出,程序在执行main函数之前,会先执行SystemInit函数。* b& U3 J& v" g& C8 [  O9 a

1 |5 K, A$ m0 c2 e0 p9 @
2.2 SystemInit函数详解
  1. void SystemInit (void)' h+ r+ `2 R+ f3 V) y
  2. {
    ' r+ ?( |, V% |5 q
  3.   /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
    % n9 }6 p6 A  \0 V
  4.   /* Set HSION bit */
    ; m1 |. J4 Z0 ]6 Y( M. ~
  5.   RCC->CR |= (uint32_t)0x00000001;: M+ w( P- n- e, Y5 ~# E# @$ c

  6. . {7 w  n+ U5 d" |6 b$ S9 B3 }
  7.   /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
    - P9 x/ L1 P5 q  Z
  8. #ifndef STM32F10X_CL
    ( Y; o& ~& C3 n+ n" V! g2 E
  9.   RCC->CFGR &= (uint32_t)0xF8FF0000;
    $ Z) }1 q$ b1 A5 u, P
  10. #else" Q  f4 k. c  k7 M! b
  11.   RCC->CFGR &= (uint32_t)0xF0FF0000;
    0 n: V* U. ?1 ]) V. _5 C0 a
  12. #endif /* STM32F10X_CL */   4 N. d1 I1 h/ ?/ B  b# ?/ h% k7 k
  13. ; A0 g5 R+ V  _1 C9 o6 u
  14.   /* Reset HSEON, CSSON and PLLON bits */
    8 e" K6 H+ ]9 ]8 }4 @; h
  15.   RCC->CR &= (uint32_t)0xFEF6FFFF;
    1 L4 W6 Z6 z3 f4 X2 x

  16. 5 d3 s0 _$ e7 Y0 e" o
  17.   /* Reset HSEBYP bit */
    2 a. ?$ h6 y; N
  18.   RCC->CR &= (uint32_t)0xFFFBFFFF;0 y1 P, y9 ]$ f; N

  19. $ e: Y' p6 m8 ^, j8 G/ z' T
  20.   /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
      r, g9 q6 q- Q, J
  21.   RCC->CFGR &= (uint32_t)0xFF80FFFF;
    " O4 ~% m5 ]) a; O% W* m4 Z
  22. ! h8 V# R+ t* N0 s! Z' X5 t
  23. #ifdef STM32F10X_CL
    3 F- D4 z8 x: E
  24.   /* Reset PLL2ON and PLL3ON bits */
    7 A8 }+ {  v0 A1 F5 V) V  n- u
  25.   RCC->CR &= (uint32_t)0xEBFFFFFF;
    8 w7 |, C& }6 O% w, e
  26. % I) q/ F7 N" R7 X
  27.   /* Disable all interrupts and clear pending bits  */
    7 n# H/ L7 _; ?
  28.   RCC->CIR = 0x00FF0000;
    & R% g+ K. @5 z9 c; Y9 q/ u

  29. ! m- C( F$ ]/ i' G2 P, f) v
  30.   /* Reset CFGR2 register */
    % C; g6 f  l+ n0 l8 [8 c2 _% L
  31.   RCC->CFGR2 = 0x00000000;- |0 Q( P. Q; U4 N- k5 h  t3 M
  32. #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)% Z, w  f" B* }) q6 X
  33.   /* Disable all interrupts and clear pending bits  */
    5 O5 _0 ]/ }5 y9 }
  34.   RCC->CIR = 0x009F0000;( i' o7 I) C3 L* K# M: S9 w4 {7 E

  35. " s5 D, k' ]! T# Q9 C! I! T$ C$ m
  36.   /* Reset CFGR2 register */, P* w5 M4 R' o( J+ o1 m3 K$ E
  37.   RCC->CFGR2 = 0x00000000;      
    * i0 u- _" u7 W0 E  G( \6 g
  38. #else
    2 O& H" H1 R  r. r1 y, J8 D8 i
  39.   /* Disable all interrupts and clear pending bits  */
    ' z; j, O3 C! d( X5 e
  40.   RCC->CIR = 0x009F0000;
    - P- `0 T9 a3 t
  41. #endif /* STM32F10X_CL */6 T, r( x; A2 \7 r
  42. , e8 A1 A% {0 {6 a6 d( ^9 N9 j: \
  43. #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL): b# o- T, d& y0 x1 @4 N
  44.   #ifdef DATA_IN_ExtSRAM
    0 D) w3 b- V  n1 P
  45.     SystemInit_ExtMemCtl();
    : V& o! Q$ }, v; v7 J. b
  46.   #endif /* DATA_IN_ExtSRAM */' m/ Y( O2 A5 Q
  47. #endif 2 E! O; N4 q" y5 W: p( B7 q. i

  48. 9 b, x" `2 o" ^7 Q3 T) T* @, T1 `& m7 s- U
  49.   /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */  G# |% [- K; G/ C' t9 i; B
  50.   /* Configure the Flash Latency cycles and enable prefetch buffer */
    ) a# A4 {* N/ U
  51.   SetSysClock();
    + N4 [& N+ J# _4 u* F$ s

  52. 3 M  |5 H% |$ @2 h( i9 ?
  53. #ifdef VECT_TAB_SRAM
    % z2 {5 ?3 a/ r* D- n& U& ]( \
  54.   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
    1 X! H/ h6 I# G; `- E( N0 O
  55. #else
    5 X, m: P6 K# o9 M
  56.   SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */' B7 Y+ N0 |6 d2 I8 U. X% V6 B2 B$ L
  57. #endif " Q+ \% o! n8 S2 U# X7 Y  r6 g; O
  58. }
复制代码

' ^1 |. `9 }$ l. G0 c$ V5 {, @7 ^  w" ^: G( L0 o0 T9 K
打开内部8M时钟:9 I3 P5 T5 T: R5 Y. X
  1. RCC->CR |= (uint32_t)0x00000001
复制代码

9 t2 G1 d! F9 @通过查看寄存器手册可知,这段代码为打开内部8M时钟。% h8 c3 e) E$ p

* V2 a! d8 n: d
微信图片_20231104190120.png

6 k* [1 [* j  u, @
# ]# U3 M6 Z$ F2 ^; n  \4 R" t设置时钟配置寄存器:$ Z5 C4 {& Y# N$ O0 _: D$ m) H, {. z
  1. #ifndef STM32F10X_CL1 U) P* C  H9 _' m
  2.   RCC->CFGR &= (uint32_t)0xF8FF0000;
    - ?) P" E( B- W& u
  3. #else" i* w3 S4 A/ q( e8 c
  4.   RCC->CFGR &= (uint32_t)0xF0FF0000;
    6 {- |; P0 V/ x" z1 _( K! P
  5. #endif /* STM32F10X_CL */   
复制代码

3 S9 }7 a9 s2 U3 w# T对应寄存器说明可查看《STM32中文参考手册_V10》的6.3.2 时钟配置寄存器(RCC_CFGR)章节。
* B( z* h2 }, l. s) }: k后续代码,有兴趣可根据《STM32中文参考手册_V10》手册,查看代码具体作用。
; ^4 L$ l, |5 L, A
/ q# S8 Y/ i0 j! l
2.3 SetSysClock()函数详解
6 s1 u. K6 F- N, G4 Z
  1. static void SetSysClock(void)7 P* a5 A5 f8 A1 V$ u/ }
  2. {6 Y/ u1 ]; e- |9 n+ a! P" k! e5 `
  3. #ifdef SYSCLK_FREQ_HSE
    # q6 ?* H- }' s4 X6 l
  4.   SetSysClockToHSE();9 w+ ^' k- A. P9 ]' _
  5. #elif defined SYSCLK_FREQ_24MHz
    / ~& d3 {0 g; q  N9 J
  6.   SetSysClockTo24();
    6 Y3 c: [4 Q- Z0 X; V  a7 j
  7. #elif defined SYSCLK_FREQ_36MHz
    / h* b( _! V0 C8 N' F
  8.   SetSysClockTo36();0 Q/ t# ?4 [& k- F# y! u. k- |
  9. #elif defined SYSCLK_FREQ_48MHz
    2 }/ L0 p) u; B# C2 q# ~9 e- J
  10.   SetSysClockTo48();
    , y5 N7 s# E' I0 X
  11. #elif defined SYSCLK_FREQ_56MHz% \; q7 |- x5 B! O- w$ [/ \+ M
  12.   SetSysClockTo56();  ' z4 B0 I0 `% M0 q* L" ~* O2 W
  13. #elif defined SYSCLK_FREQ_72MHz, Q' j1 ?" p2 l& \/ n" Z/ E
  14.   SetSysClockTo72();
    - F/ `" K7 ?- [( N) q% z: m! J% i" _7 n
  15. #endif
    : M0 |& O8 a! B& S' c
  16. }
复制代码
5 L* d  c3 d/ Z) b- k' z, G' z9 |" }4 x, b

: L3 i9 e8 J5 z0 hsystem_stm32f10x.c文件中会根据芯片的型号定义对应的宏:/ G  ?  y) {. q, n
  1. #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)$ T' Y3 @: p2 r6 {$ v& e+ x1 d9 S
  2. /* #define SYSCLK_FREQ_HSE    HSE_VALUE */! c7 U  G+ n6 ^0 l, j
  3. #define SYSCLK_FREQ_24MHz  24000000
    , c! i+ ~; f) x6 F& M
  4. #else* g: A3 V* j% p& U1 p2 P3 K
  5. /* #define SYSCLK_FREQ_HSE    HSE_VALUE */
    8 K2 f7 l" J( G0 [9 r' q" Z
  6. /* #define SYSCLK_FREQ_24MHz  24000000 */
    0 z8 ]6 L8 T$ M' K9 p
  7. /* #define SYSCLK_FREQ_36MHz  36000000 */! a6 l. Y3 B3 G  y- t/ k
  8. /* #define SYSCLK_FREQ_48MHz  48000000 */: {8 z/ c" x# P3 P
  9. /* #define SYSCLK_FREQ_56MHz  56000000 */2 w! o2 Z2 y# f: z+ p, j
  10. #define SYSCLK_FREQ_72MHz  72000000
    & I5 L" z. ], [
  11. #endif
复制代码

; N; _7 w" |, }8 Y3 时钟配置函数8 X* [5 M1 a  u, G+ U. k. B% c' `
3.1 时钟初始化配置函数
  1. void SystemInit(void);
    " e) M4 r8 p  ~- O8 @1 M  S7 a6 I
  2. SYSCLK(系统时钟)=72MHZ;
    , Y2 Z% k4 A+ G. l
  3. AHB总线时钟(HCLK=SYSCLK)=72MHZ;
    & Y3 F7 x' U1 c& S4 e9 i
  4. APB1总线时钟(PCLK1=SYSCLK/2)=36MHZ;* e" A9 ]' `, n6 H) `9 v
  5. APB2总线时钟(PCLK1=SYSCLK/1)=72MHZ;
    * J7 T9 v7 Y4 g6 }
  6. PLL主时钟=72MHZ;
复制代码

# Q# W6 j. U0 y' m& O
- J2 @: E! [4 C( P3.2 外设时钟使能配置函数
9 z- ]( k5 h4 J' x
  1. void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);, u% {+ V4 `1 J& z5 F) G
  2. void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
    0 v. I( O* b- G1 z4 T+ f& z
  3. void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
复制代码
. N5 b2 X" O0 o$ o
3.3 时钟源使能函数
  1. void RCC_HSICmd(FunctionalState NewState);
      D" q6 \% R, ~+ X  ]  S2 o
  2. void RCC_LSICmd(FunctionalState NewState);1 i& C' P8 j8 G) C, L  l. B" w
  3. void RCC_PLLCmd(FunctionalState NewState);
    2 w4 g( K% U% _. l8 V
  4. void RCC_RTCCLKCmd(FunctionalState NewState);
复制代码
9 G* E4 M' p8 e/ O

; v$ _! v% ?! z1 b. c2 \3 c3.4 时钟源和倍频因子配置函数
0 ?' V' r5 A3 {# d' N& o# T9 r- h
  1. void RCC_HSEConfig(uint32_t RCC_HSE);# B; Z8 J) ?9 o! W  `0 N. Z: _
  2. void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);4 C5 Z. D5 T+ B
  3. void RCC_HCLKConfig(uint32_t RCC_SYSCLK);
    ) s6 X" c. X+ f- p
  4. void RCC_PCLK1Config(uint32_t RCC_HCLK);
    * J- {, a0 P; ^' f
  5. void RCC_PCLK2Config(uint32_t RCC_HCLK);
复制代码
* @5 a$ V7 i3 N+ o2 T5 @7 z9 K" b: p
3.5 外设时钟复位函数
! e$ r7 a$ h7 c& K, _7 v8 t
  1. void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);, @6 }. i2 r1 S& n0 _0 M/ w1 l" B
  2. void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
复制代码
# s1 ?) C/ }$ T9 X1 \; E$ O2 G7 Q
3.6 自定义系统时钟8 h' x5 T4 l* T6 c
  1. void RCC_HSE_Config(u32 div,u32 pllm)
    2 s( P; W; m( r; V9 p, h8 W
  2. {% P6 W7 l$ a1 D9 i$ F3 w9 X! A" g
  3.     RCC_DeInit();6 k4 J; C' J( S" m( a
  4.     RCC_HSEConfig(RCC_HSE_ON);
    7 S% K6 l# m* t* h2 U
  5.     if(RCC_WaitForHSEStartUp()==SUCCESS)
    $ G" |+ a  n, I7 V$ v$ c- l9 p
  6.     {   
    0 H8 C' l1 q. R: U- }
  7.         RCC_HCLKConfig(RCC_SYSCLK_Div1);
    % D3 P% M* w4 D* l" x
  8.         RCC_PCLK1Config(RCC_HCLK_Div2);+ Q2 ~; d6 F6 s( H* w9 h
  9.         RCC_PCLK2Config(RCC_HCLK_Div1);
    $ T  r1 i1 _% d& k! Q1 C
  10.         RCC_PLLConfig(div,pllm);% S" _  @% a' V$ F. D
  11.         RCC_PLLCmd(ENABLE);     1 U' o4 i* {' V5 o
  12.     while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)
    3 s; h: f" d% D8 T. c
  13.         RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK)( M2 J; d; s1 m0 ?* k
  14.     while(RCC_GetSCLKSource()!=0x08);% M) L0 Z# J( {! i
  15. ( t( z) c8 Q' X6 C0 B) q" A7 p+ {
  16.     }
    ( O& L/ O( `# G( {5 M
  17. }
复制代码
转载自:STM32嵌入式开发
3 ]# {) `8 y" z" t+ }( @& @" G& y$ ~# t1 s, W, S. x: h
如有侵权请联系删除
) K) q. Y" F% C
3 `( [% ~* ^3 f7 C
收藏 评论0 发布时间:2023-11-4 19:02

举报

0个回答

所属标签

相似技术帖

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