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

基于STM32时钟系统经验分享

[复制链接]
攻城狮Melo 发布时间:2023-11-4 19:02
1 STM32的时钟源主要有:! A0 p8 R3 h. Z! R) A
内部时钟) L  G. W$ |% L5 o
外部时钟
# |* w2 E& X1 h' p6 @) u锁相环倍频输出时钟
% N. i% m+ o. O
微信图片_20231104190126.png
- H) [' D' X! z! C- a: t

$ G  A; n- |% p" I0 T1.1 详细介绍

& r+ l' E9 C0 B$ X& c3 [HSI(内部高速时钟)
6 d$ j* z' C. i% f$ i它是RC振荡器,频率可以达到8MHZ,可作为系统时钟和PLL锁相环的输入
, l! x4 s; R  K0 I; d4 S
& a6 q% ^$ B8 ]8 w
HSE(外部高速时钟)
4 u- F* a) H  \: ^! X2 l接入晶振范围是4-16MHZ,可作为系统时钟和PLL锁相环的输入,还可以经过128分频之后输入给RTC。
' A1 q7 z- g0 K+ g& _% x$ A4 Y. H( A7 k0 K3 I2 @- L
LSI(内部低速时钟)
  G, i* p2 ^1 I( f它是RC振荡器,频率大概为40KHZ,供给独立看门狗或者RTC,并且独立看门口只能依靠LSI作为时钟源
( q6 P3 F, t( ~5 G# `. p* t! {3 a  i. Z
LSE(外部低速时钟)
% I. g8 v- X* c  m+ k- U+ n通常外接32.768MHZ晶振提供给RTC
) C7 G4 }. u4 ~& T  m2 }
$ {: k$ L! I  @$ o/ [' V0 e
PLL(锁相环)* t" Y: |( |& S# m
用来倍频输出。因为开发板外部晶振只有8MHZ,而STM32最大工作频率是72MHZ。他可以通过HSI输入,HSE输入或两分频输入,通过PLL倍频(2-16),倍频之后输入给系统时钟。/ ~, o. }  {2 ]( Q
5 ^- ^, U9 Z2 m  m3 l0 W
MCO(时钟输出管脚)
$ u9 L* l, }% i9 [) ?通常对应STM32 PA8,它可以选择一个时钟信号输出,给外部的系统提供时钟源
6 h1 h( H, Q  x# B* h
2 y' `) w! [- g( d* ^. _
2 标准库的时钟配置9 D0 v8 u$ ^6 s  k. m
2.1 STM32启动文件
1 ^2 g1 }' d  m6 r/ k3 b" u7 L
首先打开startup_stm32f10x_hd.s,该文件为stm32的启动文件,在该文件内会发现有这么一块用汇编写的代码。
& O( y! f$ \9 B- _5 p
  1.       Reset_Handler   PROC
    $ l1 |6 k6 N  n0 c6 \
  2.             EXPORT  Reset_Handler    [WEAK]! F8 e# ]0 C6 Q0 V
  3.             IMPORT  __main% ?& @, G7 E, l0 F% f
  4.             IMPORT  SystemInit3 e  S! I+ j% q; @
  5.             LDR     R0, =SystemInit
    " F3 Y2 i( n7 X/ N9 Z! Q( v6 a+ a  a
  6.             BLX     R0               
    : I  \/ z+ l- D0 J
  7.             LDR     R0, =__main) B( t! h7 f0 E3 e+ v- f
  8.             BX      R0  T- `, @; a) B& W  j1 j9 o# x
  9.             ENDP
复制代码

5 j! G& [  Y$ l2 R9 h) j# r% ^" M' E通过这段汇编代码可以看出,程序在执行main函数之前,会先执行SystemInit函数。: G7 T; p3 h" w. j0 A0 f
( I) @$ y1 o+ t' n: L  T
2.2 SystemInit函数详解
  1. void SystemInit (void)2 ]& Y) d1 i+ S8 r3 N2 r1 k5 e
  2. {
    ( p4 z* x' Z" `3 }/ m
  3.   /* Reset the RCC clock configuration to the default reset state(for debug purpose) */+ u% b: m* ^  ]# r
  4.   /* Set HSION bit *// ~6 Q# J6 u% {% w* d$ v& n( f4 p# S
  5.   RCC->CR |= (uint32_t)0x00000001;( z) g/ I, T, ?6 ]9 O6 _' d
  6. " ?# O1 x6 M! X3 y! J+ `
  7.   /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
    9 N; m3 `/ C; n! y/ ^6 ]
  8. #ifndef STM32F10X_CL) U+ e( X0 Q3 b; Z9 R0 o2 C, r9 n  D
  9.   RCC->CFGR &= (uint32_t)0xF8FF0000;% _' n+ E, p) ]/ q2 O9 J( H
  10. #else, u: u' K( A4 {* B( C
  11.   RCC->CFGR &= (uint32_t)0xF0FF0000;/ @$ O1 A, v- v
  12. #endif /* STM32F10X_CL */   
    7 o. K6 z4 i( O6 R! {) K. G
  13. ( P6 J. ]' u: @! u! s
  14.   /* Reset HSEON, CSSON and PLLON bits */
    8 r4 x8 w: X" n  r3 ^
  15.   RCC->CR &= (uint32_t)0xFEF6FFFF;5 ]9 o* L! B' }+ J9 A( ~: L
  16. / y: W4 ?5 ?) _' W' _1 t
  17.   /* Reset HSEBYP bit */
    8 v0 p9 C5 _: p+ z6 Y" Q
  18.   RCC->CR &= (uint32_t)0xFFFBFFFF;
    ! Y& [# p, v. E* L
  19. $ e, |# u- ~( `, \- f  l. T
  20.   /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
    8 a5 F2 k& R% D
  21.   RCC->CFGR &= (uint32_t)0xFF80FFFF;0 k5 I' c0 C" o" F9 i  @# ^, v: j
  22. ; V5 M' P+ F) ^9 W) B$ U$ q
  23. #ifdef STM32F10X_CL4 P! N) {0 m; a5 d6 x1 v9 ?
  24.   /* Reset PLL2ON and PLL3ON bits */
    % [- w0 w: I9 _+ d: c
  25.   RCC->CR &= (uint32_t)0xEBFFFFFF;
    + s3 ?- _! ~' R6 k3 }: t: l* B( s4 Q" f

  26. ' I: A/ Q. r+ U* U  j/ Y
  27.   /* Disable all interrupts and clear pending bits  */
    : `) i9 b/ M/ V* |( b1 x  v2 @
  28.   RCC->CIR = 0x00FF0000;. x/ i; J2 Y. y+ v  S4 R& X/ T9 j
  29. 8 ^( z% R0 t+ L$ B) }( w
  30.   /* Reset CFGR2 register */' H+ i# a: P6 @* i
  31.   RCC->CFGR2 = 0x00000000;1 }9 o7 ?1 ~) \& c# A! C0 C$ m
  32. #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)8 t1 k; `0 d) U# k5 J
  33.   /* Disable all interrupts and clear pending bits  */: |* h5 s' x( X
  34.   RCC->CIR = 0x009F0000;
    * {; `' `$ z+ \2 v5 n

  35. ' \' ^2 t# p( A% ?( Z' C9 C
  36.   /* Reset CFGR2 register */
    & j# b) a! R' h# R$ w8 a0 G9 b* I
  37.   RCC->CFGR2 = 0x00000000;      
    ( ]9 {$ U& H7 U. S
  38. #else
    + N! s, z. T1 }- V% E* `
  39.   /* Disable all interrupts and clear pending bits  */5 i* _9 j3 ~2 @3 [
  40.   RCC->CIR = 0x009F0000;& V, J7 N6 l9 S: d- h& f4 @
  41. #endif /* STM32F10X_CL */+ F6 b0 P, u9 Y% i) r$ w- G7 f

  42. ; F  |8 f; Z; e. z4 O
  43. #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)6 X& e# l- Y4 Y: W& m6 C
  44.   #ifdef DATA_IN_ExtSRAM0 S: @! p- r6 t& C, F
  45.     SystemInit_ExtMemCtl(); % j2 }2 n; F: q2 T3 @7 p
  46.   #endif /* DATA_IN_ExtSRAM */6 Z$ k4 y/ B, f  |/ |. |
  47. #endif 0 p& G( S. H) j; N: X  q8 m
  48. / H1 V8 [" t7 A3 ], W
  49.   /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */9 ]6 k2 i, h6 B7 _$ i/ h
  50.   /* Configure the Flash Latency cycles and enable prefetch buffer */
    2 o) j  m3 l! b
  51.   SetSysClock();
    & X- P. @, R4 a- U

  52.   y# I. I0 P; ]0 `1 n) S* n/ O6 V8 Y
  53. #ifdef VECT_TAB_SRAM" a1 l* x3 W- T: [8 A
  54.   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
    ! U( \9 h9 Y4 f% u: d2 d: b
  55. #else3 E, p- f4 D( B  M: W3 L; X
  56.   SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
    + r' U& z) }  V' F% P0 |( M
  57. #endif
    ; o: u' a+ @2 _! M. y
  58. }
复制代码
+ m: f/ v8 f5 S0 K, w! f+ _
+ p# z% U7 }  Y' q0 F1 n: {
打开内部8M时钟:
9 {' c6 J) [- L' t" X
  1. RCC->CR |= (uint32_t)0x00000001
复制代码
3 F' D0 K' ]1 v3 i' k3 Q
通过查看寄存器手册可知,这段代码为打开内部8M时钟。
  z' X; `8 G1 r/ Z0 D
$ n: _5 `' `# [# y. i5 h
微信图片_20231104190120.png

- \" q$ H% l8 @# A. F7 x: M
) ?: ^: N! e# c( }, V5 Y* S设置时钟配置寄存器:" x" o* g# Z% L" [6 M8 O
  1. #ifndef STM32F10X_CL
    ! |" W2 i' f/ e: u# c- N& }* |0 K
  2.   RCC->CFGR &= (uint32_t)0xF8FF0000;
    " m# b$ n" r; H4 O/ H. u8 [0 d7 a
  3. #else$ d3 q; I' g7 t- E& P" ^
  4.   RCC->CFGR &= (uint32_t)0xF0FF0000;& g( }( Y( n+ X  M
  5. #endif /* STM32F10X_CL */   
复制代码

) o. s; G7 o  J% O% n对应寄存器说明可查看《STM32中文参考手册_V10》的6.3.2 时钟配置寄存器(RCC_CFGR)章节。& m$ _5 S4 m) M# U
后续代码,有兴趣可根据《STM32中文参考手册_V10》手册,查看代码具体作用。( e* s0 W4 {1 ?/ s- N" l* P
  n1 i$ K( D# l* D9 s, g
2.3 SetSysClock()函数详解, Z- M6 _6 ]+ D7 x- @# {6 f
  1. static void SetSysClock(void)4 W. b0 G7 Z" {! i" m
  2. {& E, B$ c% S5 I8 M) Q
  3. #ifdef SYSCLK_FREQ_HSE
    - Q- G8 H. R! w( @! w
  4.   SetSysClockToHSE();1 W1 W# z: I+ J' u1 i- @( j
  5. #elif defined SYSCLK_FREQ_24MHz( G) ]0 N! [3 a/ b' k
  6.   SetSysClockTo24();
    : }: T! L! n2 F2 [% C1 S. p
  7. #elif defined SYSCLK_FREQ_36MHz
    9 o. ^. P  ^6 n) f; Z+ \
  8.   SetSysClockTo36();
    ' y5 u0 f" p5 V
  9. #elif defined SYSCLK_FREQ_48MHz
    ' C) T1 U7 S- E% z
  10.   SetSysClockTo48();
    5 O8 d6 D, E, v5 u$ ~7 p
  11. #elif defined SYSCLK_FREQ_56MHz( `/ H) A9 S7 V( b9 Z& P5 E# \
  12.   SetSysClockTo56();  
    5 s; Q+ O+ W8 A( q
  13. #elif defined SYSCLK_FREQ_72MHz' D7 r$ a6 G# U% ]1 ~: }. q- E
  14.   SetSysClockTo72();* F, g  @+ v" v9 {/ u
  15. #endif
    + G6 X1 H  h  ^+ C# p( k! T
  16. }
复制代码
- k( E% z$ y& V' q. `, O

" Z) V# Q, y5 ~' D! G! K, [system_stm32f10x.c文件中会根据芯片的型号定义对应的宏:
, k/ a, |! Y; y& w+ Y9 H9 H
  1. #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
    $ V8 ]4 S$ `% _+ O8 `
  2. /* #define SYSCLK_FREQ_HSE    HSE_VALUE */( x3 I' P  ^7 h; {+ L8 ~2 N
  3. #define SYSCLK_FREQ_24MHz  24000000
    & \; c3 O( }+ a5 N& p2 w) }% Y& ]
  4. #else9 K- x; ]: G4 f& k, _1 C. a" Z4 s
  5. /* #define SYSCLK_FREQ_HSE    HSE_VALUE */- L$ Y2 q" h" O8 w" p5 m0 r5 {
  6. /* #define SYSCLK_FREQ_24MHz  24000000 */ / D; b, A- y9 W( Q# B3 D: L( r
  7. /* #define SYSCLK_FREQ_36MHz  36000000 */6 ~9 d* Q1 O# Y. N
  8. /* #define SYSCLK_FREQ_48MHz  48000000 */
    , X5 [4 O+ ~9 q1 D
  9. /* #define SYSCLK_FREQ_56MHz  56000000 */& ]! m% q6 h0 v4 W5 M1 m4 S
  10. #define SYSCLK_FREQ_72MHz  72000000
    : |9 R  W& v. @# N
  11. #endif
复制代码
5 z* V& y" z# d) N  f4 e8 v7 \( h
3 时钟配置函数
0 {8 z) n' _: B& ?! w# J7 k# a3 f3.1 时钟初始化配置函数
  1. void SystemInit(void);
    - }; v3 l% N4 A
  2. SYSCLK(系统时钟)=72MHZ;8 J, \3 _0 b0 H5 ?' y
  3. AHB总线时钟(HCLK=SYSCLK)=72MHZ;# e. \* [, i" s: E( Y
  4. APB1总线时钟(PCLK1=SYSCLK/2)=36MHZ;
    9 ]* W9 m) L* C1 R4 }0 o
  5. APB2总线时钟(PCLK1=SYSCLK/1)=72MHZ;
    1 n$ {  I6 ^/ }4 w6 ^
  6. PLL主时钟=72MHZ;
复制代码
) }- D7 ]3 R& ]( c" d% i
8 a4 c* x/ w9 L7 z$ c( r
3.2 外设时钟使能配置函数3 H- h2 k' g( ]' A, d- K
  1. void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
    2 ~( J, n7 Y# y
  2. void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);9 C. i( ]) c3 ?9 m  b
  3. void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
复制代码

% }* i- h' q: v+ R0 |8 I3 B8 v8 F3.3 时钟源使能函数
  1. void RCC_HSICmd(FunctionalState NewState);: h7 l* p* s0 l
  2. void RCC_LSICmd(FunctionalState NewState);
    . l& a3 ^$ T7 {& n
  3. void RCC_PLLCmd(FunctionalState NewState);
    2 V- N$ I* _9 |) q
  4. void RCC_RTCCLKCmd(FunctionalState NewState);
复制代码

( k% @- y, u5 B/ G1 Z9 J" k+ w0 e% v- b* H& Y. M
3.4 时钟源和倍频因子配置函数" u' l8 B; F0 b" {% `
  1. void RCC_HSEConfig(uint32_t RCC_HSE);( I+ s. s& L) M1 b2 Z
  2. void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);
    2 Z: M9 D2 H. c; ^4 D/ H
  3. void RCC_HCLKConfig(uint32_t RCC_SYSCLK);
    % |* s7 n$ Z' X6 a$ E- b5 b
  4. void RCC_PCLK1Config(uint32_t RCC_HCLK);3 e- E: [9 X6 [  o" \
  5. void RCC_PCLK2Config(uint32_t RCC_HCLK);
复制代码

2 d8 p+ c4 _. ^9 d( R- j; {3.5 外设时钟复位函数
, ?" z7 u, i4 q& M
  1. void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
    ; L: y+ K* {# ~
  2. void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
复制代码

( e! A- @6 Q* b4 e5 B3.6 自定义系统时钟, q2 J. S% s5 g: F5 H1 i& I* H+ i
  1. void RCC_HSE_Config(u32 div,u32 pllm)( b5 b+ I+ z& D, ^
  2. {
    : P6 \( m2 Y0 h1 i0 f6 s) K5 w# Y
  3.     RCC_DeInit();& W8 h& D' l: i5 M0 c8 B5 u" a
  4.     RCC_HSEConfig(RCC_HSE_ON);. d2 C; x* O4 ~! F+ |0 }  ~
  5.     if(RCC_WaitForHSEStartUp()==SUCCESS)" q$ f' T) Q3 @5 Y! q
  6.     {   ( F& F  K* F% d6 f% z# v4 S) o
  7.         RCC_HCLKConfig(RCC_SYSCLK_Div1);
    4 [/ ?7 ^+ [- n* M
  8.         RCC_PCLK1Config(RCC_HCLK_Div2);
    9 F% F" J/ c7 Y# B  v! ~4 @+ o! Z2 c1 T
  9.         RCC_PCLK2Config(RCC_HCLK_Div1);3 Y0 R  r3 J( B% v" g: v
  10.         RCC_PLLConfig(div,pllm);6 \5 r0 F6 v$ Q- u; B
  11.         RCC_PLLCmd(ENABLE);     ; X, K$ @4 n) ]7 e0 g1 d
  12.     while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)
    * b- V" G' k0 M- ^% J; \
  13.         RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK)) H  u4 q5 A( K3 Q( _4 e
  14.     while(RCC_GetSCLKSource()!=0x08);
      X) h/ G& j4 A% W8 T

  15. % `# j& G# A( q( T6 q# k
  16.     }
    1 X/ J" k; d5 f  Y3 `$ z
  17. }
复制代码
转载自:STM32嵌入式开发
2 f; |4 f$ w; L8 W3 M9 c2 a
3 g% C/ b; A+ F; g" h# h如有侵权请联系删除
& F( j! Z) I7 r! ^6 }
- ?5 E$ O" j" ?7 k4 w& {' O$ h& i2 S
收藏 评论0 发布时间:2023-11-4 19:02

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版