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

基于STM32时钟系统经验分享

[复制链接]
攻城狮Melo 发布时间:2023-11-4 19:02
1 STM32的时钟源主要有:
, v- o- K. o- R$ l) T内部时钟1 U& T& c5 |% |# d8 o5 `; u8 \$ N. T
外部时钟# L% c; U0 W/ |0 x3 b" f5 x# q! v
锁相环倍频输出时钟
4 h+ q2 O, S# O1 K. V7 o/ f
微信图片_20231104190126.png

4 a/ J" `! @1 a" j) c8 |$ [, ~5 z8 [7 J6 K3 @) e
1.1 详细介绍
8 A' n& N2 q$ a2 u
HSI(内部高速时钟)% m, I3 ^" m8 x) B, w3 X
它是RC振荡器,频率可以达到8MHZ,可作为系统时钟和PLL锁相环的输入
1 j( o2 [& B; H4 B: r- R
8 ?( b6 `  ]) @1 x6 ^4 O8 I
HSE(外部高速时钟)$ Z+ c; L5 ?9 `2 T0 O& u& A- D& n8 ~' A
接入晶振范围是4-16MHZ,可作为系统时钟和PLL锁相环的输入,还可以经过128分频之后输入给RTC。
7 ~3 R# v. T+ [$ p7 F: W9 d2 K% L' A" {0 `6 p5 e
LSI(内部低速时钟)* Q' N, G2 V7 H% T) m
它是RC振荡器,频率大概为40KHZ,供给独立看门狗或者RTC,并且独立看门口只能依靠LSI作为时钟源  h9 T2 \( I/ T8 c1 g; X; u5 R

# U$ r1 f' `' ^; S! x, F
LSE(外部低速时钟)( F1 ~* m* E6 Z1 `' x
通常外接32.768MHZ晶振提供给RTC% a8 f' U" i$ u: ?

8 n: u* G# z; b  r" i, A
PLL(锁相环)
0 `% j( a% f! ]2 Q用来倍频输出。因为开发板外部晶振只有8MHZ,而STM32最大工作频率是72MHZ。他可以通过HSI输入,HSE输入或两分频输入,通过PLL倍频(2-16),倍频之后输入给系统时钟。
, k1 L5 D+ S5 V+ T' X3 g$ G. b7 k$ D7 Q# ]0 }7 U9 \7 }
MCO(时钟输出管脚)0 C3 y8 b4 n0 Q0 G2 `
通常对应STM32 PA8,它可以选择一个时钟信号输出,给外部的系统提供时钟源7 ~$ f2 O8 J' `* \, B# D
0 j$ U1 ~9 h. A4 U) x
2 标准库的时钟配置
8 Y0 E5 X# U* t$ d! N$ y& m2.1 STM32启动文件
' A( w" e, @+ @/ Q
首先打开startup_stm32f10x_hd.s,该文件为stm32的启动文件,在该文件内会发现有这么一块用汇编写的代码。
9 a: c) t0 l6 d. P; G. {" w. N
  1.       Reset_Handler   PROC8 v) {" g8 ]/ N9 t$ s( g; I
  2.             EXPORT  Reset_Handler    [WEAK]* W% V" Z4 y7 j! j! F
  3.             IMPORT  __main
    4 O! e7 v. D7 s  Q, O+ t& m
  4.             IMPORT  SystemInit
    - c# g' a" v/ [( O6 O) f* w* {1 M0 n
  5.             LDR     R0, =SystemInit
    - L2 U0 I) t( Q$ @4 \
  6.             BLX     R0               
    % H! t( |8 a6 k  A3 O7 Q! V
  7.             LDR     R0, =__main
    # c$ K! m! H9 `; \+ C
  8.             BX      R07 J8 F4 n$ r2 V! b4 @
  9.             ENDP
复制代码
) b4 F! d, X' }( M& [& v# |
通过这段汇编代码可以看出,程序在执行main函数之前,会先执行SystemInit函数。
  J7 O+ y* }: {8 y; B
* G1 M! F, @8 E9 ~2 l3 z
2.2 SystemInit函数详解
  1. void SystemInit (void)2 o* Q+ a* }' |! z' i: D
  2. {
    " w9 X, w. ]- g; O+ G4 J! ?' [
  3.   /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
    ' M( s& s' a2 D2 {! G' V
  4.   /* Set HSION bit */2 D2 e; w1 N. a( r7 @
  5.   RCC->CR |= (uint32_t)0x00000001;1 |: M) |, u5 P. j
  6. % z* q4 b$ e. {; H  L
  7.   /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
    4 F$ v  T* h$ I6 @4 n2 K
  8. #ifndef STM32F10X_CL* y  `  N& P% p, @
  9.   RCC->CFGR &= (uint32_t)0xF8FF0000;
    7 y+ A6 {! Y2 p4 A; z9 j
  10. #else
    - p/ I6 z! l+ O1 G
  11.   RCC->CFGR &= (uint32_t)0xF0FF0000;
    * k4 H: B4 J' T1 v
  12. #endif /* STM32F10X_CL */   
    1 Y% y" i. t  |' F
  13. 8 Z* u2 T4 f( [: I( a9 L3 t
  14.   /* Reset HSEON, CSSON and PLLON bits */
    + j/ c1 p3 N) Y9 L3 E
  15.   RCC->CR &= (uint32_t)0xFEF6FFFF;
    , V  |+ H' p4 R3 s/ U9 q
  16. : _6 }; D/ S  E- {/ Q% U. V
  17.   /* Reset HSEBYP bit */
    % _3 X3 w2 x( q; _: V2 S5 m
  18.   RCC->CR &= (uint32_t)0xFFFBFFFF;& ~4 U& P8 c. a& ^
  19. 9 t8 L' r( k* S2 ]8 H% W7 S, [3 }
  20.   /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
    # b. q- c9 b& _* Q2 f( C* {% Q: n+ k5 u8 W
  21.   RCC->CFGR &= (uint32_t)0xFF80FFFF;
    & i) ^, l3 i# c- L% d( I  a

  22. ' j  E; ~# h) ]$ ?! l1 u* j9 X
  23. #ifdef STM32F10X_CL
    2 S8 j" v* y1 x4 ?
  24.   /* Reset PLL2ON and PLL3ON bits */
    ; M2 j: S% n2 h0 H1 k, S% P
  25.   RCC->CR &= (uint32_t)0xEBFFFFFF;1 D$ U- M( a+ @! R" k: K/ m, V4 l

  26. ) F3 C, L- ^" z& N
  27.   /* Disable all interrupts and clear pending bits  */! o. @6 k3 w5 J* T
  28.   RCC->CIR = 0x00FF0000;
      ?) L/ F* q& i3 x
  29. ! ]: C% m7 G7 i% r. v/ j
  30.   /* Reset CFGR2 register */$ h: x2 f% V3 b+ a2 V
  31.   RCC->CFGR2 = 0x00000000;' |9 G; F3 U& n5 n: g4 e6 _
  32. #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
    - I4 e! I9 H, {& v
  33.   /* Disable all interrupts and clear pending bits  */
    " d2 v% V$ Y9 u$ n
  34.   RCC->CIR = 0x009F0000;
    " s- H/ `2 I, t1 R, v8 E# N. g
  35. 3 t; f' I* E) V  g+ ~3 T8 M) m- x: `
  36.   /* Reset CFGR2 register */5 T8 z& _8 b: i
  37.   RCC->CFGR2 = 0x00000000;      ( F2 a( l% `2 N$ Q! t  n
  38. #else
    : |0 f! h  _' g! G! h
  39.   /* Disable all interrupts and clear pending bits  */  {" V4 i9 l; ]* j% Y
  40.   RCC->CIR = 0x009F0000;- u$ i% l$ O) x% K3 I+ f
  41. #endif /* STM32F10X_CL */
    3 {. D: B5 ?3 s2 `8 \0 P1 W4 M
  42.   q* _- {. \9 S6 N, p7 H
  43. #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)( B+ h0 y" i& J
  44.   #ifdef DATA_IN_ExtSRAM
    . T  D- m6 n8 {/ S
  45.     SystemInit_ExtMemCtl();
    1 E' G2 e/ _; ]  S9 c) q
  46.   #endif /* DATA_IN_ExtSRAM */
    # U0 K/ |- d3 o+ |
  47. #endif
    , K: [/ s3 e. T

  48. * F& A9 V; q6 S
  49.   /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */& M* _% e# m0 t: o- V- K
  50.   /* Configure the Flash Latency cycles and enable prefetch buffer */
    5 R, }! p  N1 [9 q( [1 V' F4 I, h5 I
  51.   SetSysClock();
    2 P  d* X2 o( C- o
  52. * k* a9 U3 j7 b) X
  53. #ifdef VECT_TAB_SRAM
    & x, f3 q: r' {2 u
  54.   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */: }% `* _+ ~, F& s) U
  55. #else
    * [% U6 o4 x2 |+ z7 D( A4 w# ]
  56.   SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
    * F: \" m' }2 W, a" I, I* m& A. y
  57. #endif   w8 u  [, ^& u( y- P) g- L
  58. }
复制代码
" B# _4 [1 @$ G

/ f. l% I) o/ |9 I打开内部8M时钟:
8 h5 o4 A. W1 Z1 E9 @, P4 i
  1. RCC->CR |= (uint32_t)0x00000001
复制代码
" \& {( L" }6 N0 A, h
通过查看寄存器手册可知,这段代码为打开内部8M时钟。/ e( l* [0 O' y( s0 j9 y& A5 q+ @
3 g3 n( m& Y( R7 g) R. V0 [) B
微信图片_20231104190120.png

( ^) j  l( w$ V- q. o5 B
: F. K3 ~5 O$ e2 b设置时钟配置寄存器:
/ {' }; y2 Z8 D( G. l7 ]7 Q
  1. #ifndef STM32F10X_CL3 j. H' A) i$ \3 V* ~' `9 w! |
  2.   RCC->CFGR &= (uint32_t)0xF8FF0000;
    6 O0 Q! I" v7 i
  3. #else
    4 w& R2 q0 g( D& E) P- b- X
  4.   RCC->CFGR &= (uint32_t)0xF0FF0000;! t9 F' @( [0 @/ g5 a3 R' H* Y* s1 a9 @
  5. #endif /* STM32F10X_CL */   
复制代码

  d* i8 X' V) A/ a, ^5 k对应寄存器说明可查看《STM32中文参考手册_V10》的6.3.2 时钟配置寄存器(RCC_CFGR)章节。
' T5 s2 e8 M+ c5 \8 y5 ^0 _+ p/ u后续代码,有兴趣可根据《STM32中文参考手册_V10》手册,查看代码具体作用。$ p$ X9 j6 i8 A8 a% d

1 U! R. ^/ E0 P+ M
2.3 SetSysClock()函数详解1 e7 Y; H7 @, A
  1. static void SetSysClock(void)3 A+ ], n6 t' J, T, ?+ D. _
  2. {: V. P$ v" `3 M3 U1 T9 g
  3. #ifdef SYSCLK_FREQ_HSE
    # V. @' u7 V& z, r- O  Q
  4.   SetSysClockToHSE();
    7 F( T2 m% R$ X! M+ Y5 Q
  5. #elif defined SYSCLK_FREQ_24MHz7 @( `% ?: w5 L/ S! Y' x$ p
  6.   SetSysClockTo24();
    ( H& {3 X. h0 n# I0 `  R
  7. #elif defined SYSCLK_FREQ_36MHz
    " e# K- k$ M$ Q) N* S+ R
  8.   SetSysClockTo36();4 W: n& [6 n$ a! _
  9. #elif defined SYSCLK_FREQ_48MHz
    5 p! t5 I7 G8 C% l9 A, r3 g3 n- V
  10.   SetSysClockTo48();  z8 z' _4 F. b% i
  11. #elif defined SYSCLK_FREQ_56MHz
    2 G  _. F7 ~( ]1 I0 a
  12.   SetSysClockTo56();  ) J/ _9 l: M2 E1 {" T6 w
  13. #elif defined SYSCLK_FREQ_72MHz
    5 g0 ]2 M: _/ m# ]% Y1 z4 n
  14.   SetSysClockTo72();
    - J* L4 m& [* }
  15. #endif8 J  L& s7 V5 Y; s- T
  16. }
复制代码

% ~% C! s, F8 i; R+ @* X7 W" u7 k
- J9 O7 v' k2 y  s7 ^' d5 V7 usystem_stm32f10x.c文件中会根据芯片的型号定义对应的宏:
8 n* ?! M$ l; ?$ s( {! x5 N, u, H
  1. #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)" \. G$ \. e' G2 v# |
  2. /* #define SYSCLK_FREQ_HSE    HSE_VALUE */) T, P$ h0 n$ z4 W5 x( y' A
  3. #define SYSCLK_FREQ_24MHz  24000000
    4 c! b+ ^9 W5 u. n; M
  4. #else" ^1 ]5 Z# s7 l" D: K5 P
  5. /* #define SYSCLK_FREQ_HSE    HSE_VALUE */7 C; r- r6 M& S
  6. /* #define SYSCLK_FREQ_24MHz  24000000 */ 4 q( L& f* |9 C9 O- D3 g1 N
  7. /* #define SYSCLK_FREQ_36MHz  36000000 */$ @* h6 @" y) b( J+ C- b/ x. f
  8. /* #define SYSCLK_FREQ_48MHz  48000000 */1 n- x% v9 J1 m2 ~
  9. /* #define SYSCLK_FREQ_56MHz  56000000 */* y0 e$ n2 L3 h4 Z
  10. #define SYSCLK_FREQ_72MHz  72000000
    5 x+ {: l( I9 A6 v9 u, K
  11. #endif
复制代码
! d! R1 ^  G; j' N
3 时钟配置函数8 u- X3 [2 ]9 n7 g% s( D
3.1 时钟初始化配置函数
  1. void SystemInit(void);
    6 `( Z, G. U( y4 {' {" x" I
  2. SYSCLK(系统时钟)=72MHZ;2 y, O1 t' Y; M% _9 A: }2 S
  3. AHB总线时钟(HCLK=SYSCLK)=72MHZ;" i9 [: _  ?6 }2 [4 F
  4. APB1总线时钟(PCLK1=SYSCLK/2)=36MHZ;
    0 [  m/ N/ y$ b: k
  5. APB2总线时钟(PCLK1=SYSCLK/1)=72MHZ;
    7 M; m9 I5 Z, _# t' E* s5 R1 e
  6. PLL主时钟=72MHZ;
复制代码
6 R% v4 j, V! |8 W& C$ o1 F

0 W/ R  v4 ]7 c* T! X9 s3.2 外设时钟使能配置函数  [: I- W" j! s9 ~+ w' _; ]
  1. void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);9 U! j5 E# I. N5 B+ \
  2. void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
    " ~3 U6 D2 W, c
  3. void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
复制代码
7 x8 T6 U5 a: A' q( m5 n6 d: j
3.3 时钟源使能函数
  1. void RCC_HSICmd(FunctionalState NewState);
    ; u# g( {/ w& O% d. r
  2. void RCC_LSICmd(FunctionalState NewState);
    : j) z; y) Y' \3 `0 ~
  3. void RCC_PLLCmd(FunctionalState NewState);
    * q5 v: J* ^# x: M* e! ?, X% T
  4. void RCC_RTCCLKCmd(FunctionalState NewState);
复制代码
/ E" s9 w0 c" C; d( u

* j3 u7 h3 M* D# j  v9 }3.4 时钟源和倍频因子配置函数
7 u6 ?- v8 ]0 |! a
  1. void RCC_HSEConfig(uint32_t RCC_HSE);
    7 J( P4 L3 J6 G6 F& K" i
  2. void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);
    4 x3 T7 ^6 Q% J& i$ g9 G+ s
  3. void RCC_HCLKConfig(uint32_t RCC_SYSCLK);7 ], N3 [2 ?  n7 ~3 \5 m1 O( G
  4. void RCC_PCLK1Config(uint32_t RCC_HCLK);
    - |7 r4 b5 h& [6 L
  5. void RCC_PCLK2Config(uint32_t RCC_HCLK);
复制代码

  P( t# C% u. w4 I2 n; f9 C8 F2 S3.5 外设时钟复位函数
3 A/ Q% F2 ], C
  1. void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
    ! U( L  O  \6 I# S
  2. void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
复制代码

! ~, h6 r5 x/ w/ k9 y3.6 自定义系统时钟
! S' o( T; G+ e/ Q! R9 [; t
  1. void RCC_HSE_Config(u32 div,u32 pllm)* H: [" N- ?: t% J& f
  2. {. F% S; J1 L2 p" _9 z, L& K- f% \
  3.     RCC_DeInit();8 @$ x' I$ D9 q  V# p
  4.     RCC_HSEConfig(RCC_HSE_ON);. @% T( m6 _. r* k3 g
  5.     if(RCC_WaitForHSEStartUp()==SUCCESS)4 P. x/ I! l  S- N
  6.     {   ; O1 U$ f% _  w
  7.         RCC_HCLKConfig(RCC_SYSCLK_Div1);" X3 r: P4 i8 I0 D  e7 `1 B
  8.         RCC_PCLK1Config(RCC_HCLK_Div2);
    $ a. Y# X. j8 b* h3 k7 j: v3 S5 {
  9.         RCC_PCLK2Config(RCC_HCLK_Div1);
    3 p0 ]' T( u! g% P6 J8 P
  10.         RCC_PLLConfig(div,pllm);
    ; W, s* x  g  |9 X' L1 e
  11.         RCC_PLLCmd(ENABLE);     
    . L9 D& o: j* q& }. u+ }. D% \
  12.     while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)
    ' q  C# _) X1 j: I& V5 Z) [0 m. R- ~
  13.         RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK)
    + ^6 W! h) M0 q; `
  14.     while(RCC_GetSCLKSource()!=0x08);& C& L/ N# h! H% G7 s# |3 ]

  15. 4 m$ U/ k7 [2 ]. x/ Q4 o
  16.     }
    2 N3 `3 Z8 V$ I  M! w: C" Q
  17. }
复制代码
转载自:STM32嵌入式开发
4 g& u. d3 b- D: _" j+ z" L& l  D
* X$ j: v, p- i( ]) I如有侵权请联系删除0 s/ }# Q8 C- ]0 P5 i6 A/ a
2 o& S8 j4 T, P/ x( a
收藏 评论0 发布时间:2023-11-4 19:02

举报

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