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

基于STM32时钟系统经验分享

[复制链接]
攻城狮Melo 发布时间:2023-11-4 19:02
1 STM32的时钟源主要有:- ]5 K! ^7 w$ z" O  B+ M
内部时钟* G$ D7 F, T+ u3 @$ y9 g0 ?
外部时钟
: x4 g& j" D  U* h! w锁相环倍频输出时钟$ y; [& e  {3 k0 ]
微信图片_20231104190126.png
8 {5 i% S* B: `6 @. e2 u2 B: U: R

5 _# N2 o% ^8 w1 F) A1.1 详细介绍

, G) z( }5 G/ u2 EHSI(内部高速时钟)  ]  w, p! `+ b+ J& H# y4 S
它是RC振荡器,频率可以达到8MHZ,可作为系统时钟和PLL锁相环的输入8 K+ g9 A+ T* _8 l( |/ Q
2 c% o5 [$ O" }( G3 l( O# S
HSE(外部高速时钟)4 t# x$ Y0 ~' K: |8 |
接入晶振范围是4-16MHZ,可作为系统时钟和PLL锁相环的输入,还可以经过128分频之后输入给RTC。6 K, W& G3 ^5 [5 V* }* O- M+ x
4 K+ D4 d% t' C" S1 D0 s3 T
LSI(内部低速时钟)9 ~+ w1 h- Z1 M, e4 V
它是RC振荡器,频率大概为40KHZ,供给独立看门狗或者RTC,并且独立看门口只能依靠LSI作为时钟源1 Q* r: b/ h7 I+ B0 l& \6 s1 r2 M; r

: d% {% l# ^6 h' H. R" T1 {' Y
LSE(外部低速时钟)
& ^: {% S2 g" Y" a  h# [$ H! I通常外接32.768MHZ晶振提供给RTC9 C+ B3 g# j( E* I& I! ~

0 Z  y$ l) @+ M/ c1 [! I5 A/ W; B
PLL(锁相环)7 }1 B" m) m% X
用来倍频输出。因为开发板外部晶振只有8MHZ,而STM32最大工作频率是72MHZ。他可以通过HSI输入,HSE输入或两分频输入,通过PLL倍频(2-16),倍频之后输入给系统时钟。
& P4 M+ k- Q7 ?5 g& p2 x6 g. B- |# p% [$ C& E3 i
MCO(时钟输出管脚)
- A0 }6 e& H1 k, v% X7 R5 u通常对应STM32 PA8,它可以选择一个时钟信号输出,给外部的系统提供时钟源8 s$ H- Q  Z! C

6 N- C6 j0 q, \0 M! a7 U; i. o0 x
2 标准库的时钟配置
8 r1 ]: ^3 p- T/ o9 d5 [2.1 STM32启动文件

' t# M. A7 }8 G5 w4 K$ w" ~首先打开startup_stm32f10x_hd.s,该文件为stm32的启动文件,在该文件内会发现有这么一块用汇编写的代码。
* o- ?# u% ]# B0 }5 L& p9 E3 x
  1.       Reset_Handler   PROC7 G7 O0 S; d* c: w/ L5 B4 D
  2.             EXPORT  Reset_Handler    [WEAK]
    7 u2 E9 `3 T! A- Z( w5 ?
  3.             IMPORT  __main' K) r! ]$ V. g5 p
  4.             IMPORT  SystemInit
    7 E; a- ], B9 h6 g8 @  a  `& d
  5.             LDR     R0, =SystemInit! s3 r; V) N% [$ d1 A* E/ k
  6.             BLX     R0               
    3 Q" _1 S9 R: M4 ?, \$ c8 Y/ @# X
  7.             LDR     R0, =__main
    # a4 G4 U" Z, V9 H2 c, w0 }
  8.             BX      R0+ ]" n2 a  O# i9 x0 Q* v( J6 |
  9.             ENDP
复制代码
1 r, d4 u+ k& R% a5 w
通过这段汇编代码可以看出,程序在执行main函数之前,会先执行SystemInit函数。: U# S& K. Q' E5 M9 H; J
) q6 a' ^: r& ^& U. {, q( G
2.2 SystemInit函数详解
  1. void SystemInit (void)
    5 v) x2 f! Q7 F. x* a. y: {
  2. {6 B0 n) @* E, y3 o& S' J/ R4 N  u  V
  3.   /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
    3 K& K) X, ]) ?" c$ N) a
  4.   /* Set HSION bit */7 n6 g/ k. P# C4 Q5 {* T% W% e( A
  5.   RCC->CR |= (uint32_t)0x00000001;- A9 v- G0 T( b
  6. 5 s8 N2 y; ?( b& X! n
  7.   /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */- X8 K1 ?* j2 |0 G8 D
  8. #ifndef STM32F10X_CL
    3 |" f0 O! o7 ?6 Q& j6 s) @
  9.   RCC->CFGR &= (uint32_t)0xF8FF0000;! G2 U% H+ d4 g/ `$ k/ O/ J
  10. #else
    0 G  q) L: I! l( R" o. K
  11.   RCC->CFGR &= (uint32_t)0xF0FF0000;
    * f: d- c9 @2 V) T
  12. #endif /* STM32F10X_CL */   0 H# T; A) K9 M2 O. p

  13. 1 [6 z2 }( M% ]4 ?% i3 l
  14.   /* Reset HSEON, CSSON and PLLON bits */* U. n* n$ r  j1 H7 e) V
  15.   RCC->CR &= (uint32_t)0xFEF6FFFF;
    * S$ M' U3 v- N4 Z

  16. 0 C- ^- Z; F5 P: i
  17.   /* Reset HSEBYP bit */9 s4 b/ t' C" C' x  j3 T% J
  18.   RCC->CR &= (uint32_t)0xFFFBFFFF;; s. z* H, h6 j. _) \/ v  @+ o

  19. / g8 \0 a1 n' f) d- {
  20.   /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
    # p) C8 }$ b3 U$ ]% h6 H$ t. X( O
  21.   RCC->CFGR &= (uint32_t)0xFF80FFFF;
      M. u0 T' g5 o% n6 L8 b

  22. 8 Q6 P4 I1 r: x( [( ?3 Y
  23. #ifdef STM32F10X_CL
    ! H. X6 Y4 J  w
  24.   /* Reset PLL2ON and PLL3ON bits */0 U( J" M- x% X; s- o8 J0 \$ S
  25.   RCC->CR &= (uint32_t)0xEBFFFFFF;3 {2 R9 `" T6 y/ Y

  26. # }' P3 h( c+ c4 f) g8 m
  27.   /* Disable all interrupts and clear pending bits  */
    1 n  P9 E7 d( |7 {) ?" A% t1 l
  28.   RCC->CIR = 0x00FF0000;
    . S6 K; J5 J2 Z" C& [( x% N, b

  29. $ X4 V7 O1 o* r5 z/ S. }- k
  30.   /* Reset CFGR2 register */
    ! |* f! v0 x' k% z% w
  31.   RCC->CFGR2 = 0x00000000;  C8 p: v; i6 E6 Z4 L. N- L
  32. #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)* h* q0 ^6 Z/ Q! b, S" B6 ~, {! \1 o
  33.   /* Disable all interrupts and clear pending bits  */
      I, W0 N( r2 @
  34.   RCC->CIR = 0x009F0000;
    ; p6 @3 i: c! a" U7 `8 S( n- j

  35. * E* B, c. e2 K; }
  36.   /* Reset CFGR2 register */
    - F2 @' K% X; N
  37.   RCC->CFGR2 = 0x00000000;      % G3 `, J8 Y$ V; s5 ?, q  Q$ ^; O. L
  38. #else
    ! S/ h/ M1 x/ R
  39.   /* Disable all interrupts and clear pending bits  */
    ( X5 Y5 L2 R4 J8 G: f3 N4 @! l
  40.   RCC->CIR = 0x009F0000;
    ( T' ~5 @$ t  ]4 B# O9 x% ]4 S8 W
  41. #endif /* STM32F10X_CL */
    2 @7 d5 k/ u8 q. a
  42. ) V! p4 K6 f( y! c, N5 ]- Q
  43. #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
    % W% h/ J! o% ]# \' j6 U
  44.   #ifdef DATA_IN_ExtSRAM4 Z7 E  h- B: Q) m- m3 w! ~
  45.     SystemInit_ExtMemCtl();
    - n$ _- v% v2 [& d
  46.   #endif /* DATA_IN_ExtSRAM */' g( \. Y+ l# ^* L, O0 x
  47. #endif
    : k' F8 ?7 G6 k. J% I- Y

  48. 1 h  _0 M3 \# x2 _+ U$ ]! Q
  49.   /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
    + j# f3 n) v/ ]* c: m
  50.   /* Configure the Flash Latency cycles and enable prefetch buffer */
    7 ~* @1 Y# i1 a) d+ s( k
  51.   SetSysClock();7 z' A5 E8 Y" ~! }' f2 {0 M+ `" G

  52. 6 p6 V7 e9 ?; H) t: q2 l! W' C
  53. #ifdef VECT_TAB_SRAM
    : k4 P" _. n' z
  54.   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */( ]8 d5 T( u# k9 F- g% \
  55. #else9 [+ i9 O$ @! L& ]7 o; a
  56.   SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */% S8 G7 x/ q5 ?& E
  57. #endif
    0 J3 f! R6 U9 B, A; W
  58. }
复制代码
5 A, j0 E: @3 e
& o0 O9 q6 a  N
打开内部8M时钟:
% L9 @' ^: h" X, y8 x3 A$ u9 J, q
  1. RCC->CR |= (uint32_t)0x00000001
复制代码
6 O# Y0 n$ l. i* X* t. |
通过查看寄存器手册可知,这段代码为打开内部8M时钟。
, o2 s7 k% ~2 Q. h- e9 E! [' a/ s
4 Y* ^" S1 @5 I$ F$ z1 ]7 y
微信图片_20231104190120.png

. `9 G( |; k) [  _5 o
$ N* O7 @7 R4 L: @设置时钟配置寄存器:
$ d: o# U  _  R1 j
  1. #ifndef STM32F10X_CL
    * Y! P- ?6 z. Q! ?) n% E( G* D
  2.   RCC->CFGR &= (uint32_t)0xF8FF0000;
    1 f2 S5 _# U3 w$ L
  3. #else3 T* S$ G$ O8 ?: `( Y7 S7 Z5 f
  4.   RCC->CFGR &= (uint32_t)0xF0FF0000;4 _# ^' g, N$ v! {
  5. #endif /* STM32F10X_CL */   
复制代码
1 N/ d$ T* J6 ^# [
对应寄存器说明可查看《STM32中文参考手册_V10》的6.3.2 时钟配置寄存器(RCC_CFGR)章节。% T# ^5 Y6 c3 H$ z& V. R& s: L
后续代码,有兴趣可根据《STM32中文参考手册_V10》手册,查看代码具体作用。
8 ^: }1 a& j; g; }4 _' l6 F2 L7 X. Y$ ?% A( v4 A2 S/ M
2.3 SetSysClock()函数详解
) X7 q. v+ k' J5 K* J3 t( C% L
  1. static void SetSysClock(void)
    / K: a# M1 }2 M2 u3 ?+ B
  2. {
    ! z" k' m0 X+ I8 [6 T. i$ `
  3. #ifdef SYSCLK_FREQ_HSE
    ; J* H. ^# m8 k' d
  4.   SetSysClockToHSE();
    $ G) [) D- T' ]
  5. #elif defined SYSCLK_FREQ_24MHz
      e* R* N+ L# Q
  6.   SetSysClockTo24();, N* `: _2 U1 w* _' }
  7. #elif defined SYSCLK_FREQ_36MHz
      u5 s7 V4 P4 a& r8 J1 T7 ^
  8.   SetSysClockTo36();
    3 C6 _) T5 R2 Y  a3 d3 g# Y7 R
  9. #elif defined SYSCLK_FREQ_48MHz
    - e4 z$ ^! j" {6 Q
  10.   SetSysClockTo48();( Y0 q. }2 {' {0 M
  11. #elif defined SYSCLK_FREQ_56MHz% l' K7 w. O6 E+ \3 }" e
  12.   SetSysClockTo56();  
    0 R9 ~: R( b$ v* a
  13. #elif defined SYSCLK_FREQ_72MHz/ ~$ V# g( d  ?: Y4 m
  14.   SetSysClockTo72();) G0 g& O. b: W5 R. U9 @* s
  15. #endif$ x% Y: U$ B8 K/ J
  16. }
复制代码
: g5 t4 f1 e% i( f7 X

- u- U7 W% b* Q$ g; a$ _system_stm32f10x.c文件中会根据芯片的型号定义对应的宏:: {- u0 X+ z! y
  1. #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)2 A- P2 `& ]" s, `) S, x
  2. /* #define SYSCLK_FREQ_HSE    HSE_VALUE */! Y1 ^, e/ a1 o" p
  3. #define SYSCLK_FREQ_24MHz  24000000, ~- A: ?5 ?/ G$ `, C
  4. #else6 d3 U2 ~- `9 z5 k# I" ?" p+ g2 q
  5. /* #define SYSCLK_FREQ_HSE    HSE_VALUE */" q: o1 Y9 }7 s7 |8 B% \* d
  6. /* #define SYSCLK_FREQ_24MHz  24000000 */
    : B. Q- p- ^5 X/ R6 U$ L- b
  7. /* #define SYSCLK_FREQ_36MHz  36000000 */8 [* j: @6 o4 E7 x: x" H$ `3 T
  8. /* #define SYSCLK_FREQ_48MHz  48000000 */
    " I6 ~% C- H3 j$ S1 n7 q# g
  9. /* #define SYSCLK_FREQ_56MHz  56000000 */
    * g$ C$ L, i# P6 H
  10. #define SYSCLK_FREQ_72MHz  72000000
    # b  C6 _! Q4 |
  11. #endif
复制代码

( O! c, n# o7 v. j3 时钟配置函数
2 ^( U4 p4 S! L/ u7 K' ]/ o3.1 时钟初始化配置函数
  1. void SystemInit(void);
    5 _8 u, s" ?$ [; C: v
  2. SYSCLK(系统时钟)=72MHZ;) f" `) V: E6 O3 |, {( {
  3. AHB总线时钟(HCLK=SYSCLK)=72MHZ;( U' d' m3 b7 G% }
  4. APB1总线时钟(PCLK1=SYSCLK/2)=36MHZ;
    9 F3 `) d8 A  m  s5 n
  5. APB2总线时钟(PCLK1=SYSCLK/1)=72MHZ;
    3 v, e2 j4 S( }. X$ X7 x
  6. PLL主时钟=72MHZ;
复制代码

  O& K/ [$ k% N6 C# V; F
3 R; I+ V1 q+ Y; f0 r9 y3.2 外设时钟使能配置函数: X% C8 K" R) A
  1. void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
      e2 P7 k4 `$ X9 J/ R
  2. void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);- Y3 K) p- ?' n# c+ k2 b
  3. void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
复制代码
- g& W( c( T- D* p: K
3.3 时钟源使能函数
  1. void RCC_HSICmd(FunctionalState NewState);: Y$ c  p: O5 ^, }) v; ]
  2. void RCC_LSICmd(FunctionalState NewState);
    6 m. Y0 `1 H8 y4 e& N3 G( @% K) D
  3. void RCC_PLLCmd(FunctionalState NewState);6 O1 g$ z0 r- M/ g6 r
  4. void RCC_RTCCLKCmd(FunctionalState NewState);
复制代码

4 q$ |& i; k. M' N, F
6 a$ m9 G0 U+ M* U3.4 时钟源和倍频因子配置函数4 l/ P5 M! w1 o* g, f  B9 O
  1. void RCC_HSEConfig(uint32_t RCC_HSE);
    + ?/ y8 i! N. h# p
  2. void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);+ R% z, s. `9 `( @0 ^
  3. void RCC_HCLKConfig(uint32_t RCC_SYSCLK);7 H9 i9 x/ V" j7 e
  4. void RCC_PCLK1Config(uint32_t RCC_HCLK);
    2 W: t# h' g3 B( E" P
  5. void RCC_PCLK2Config(uint32_t RCC_HCLK);
复制代码

% D( c1 J: o1 ^8 B  k$ b3 b3.5 外设时钟复位函数) b& {8 W# \7 Q
  1. void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);2 d; h4 S7 V& s+ D- \6 p; n
  2. void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
复制代码

) s" q- s$ w, x3.6 自定义系统时钟
; L  W9 d1 i2 F* t  @
  1. void RCC_HSE_Config(u32 div,u32 pllm)
    6 X* @7 t& I' `' w0 m
  2. {$ d, m) J* L$ `, k& r: b
  3.     RCC_DeInit();
    4 P) I9 G1 V& B: J1 Q4 a$ [
  4.     RCC_HSEConfig(RCC_HSE_ON);6 Q$ W: k9 A* R' C
  5.     if(RCC_WaitForHSEStartUp()==SUCCESS)' s  E# q- g/ H8 A+ `
  6.     {   
    ' H6 m1 P& h" @5 j4 F
  7.         RCC_HCLKConfig(RCC_SYSCLK_Div1);
    5 R" Y+ W- a# r
  8.         RCC_PCLK1Config(RCC_HCLK_Div2);
    & ~8 X" y& Z) O3 O9 q
  9.         RCC_PCLK2Config(RCC_HCLK_Div1);, k8 r. x- m2 \& U
  10.         RCC_PLLConfig(div,pllm);
    4 ?& D7 I1 x4 t7 t
  11.         RCC_PLLCmd(ENABLE);     
    8 Q' d# t: o$ V- k# S' F4 F
  12.     while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)$ ?% u8 L1 ^  {6 y1 g
  13.         RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK)! p0 a; K4 I, z' L9 Q
  14.     while(RCC_GetSCLKSource()!=0x08);
    : i$ r% w# T" X& {

  15. * a. e; ^% F% p3 u, L' M0 v7 ]
  16.     }1 _1 |: `3 u. ~
  17. }
复制代码
转载自:STM32嵌入式开发
8 t( i; j# H7 F" i6 p  w+ f' G% O- J. N0 `" @. {: S, H
如有侵权请联系删除
9 c9 P* R/ l- @" {7 D% h7 z
/ n; [; {4 j' q- T+ b7 c* J$ x  y" u
收藏 评论0 发布时间:2023-11-4 19:02

举报

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