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

STM32时钟详解

[复制链接]
flyingstar 发布时间:2025-12-4 15:21
STM32时钟源介绍1. STM32的时钟源主要有:
  • 内部时钟
  • 外部时钟
  • 锁相环倍频输出时钟
    ( K2 t: q: X; c* f- N0 [
    640.png 5 G5 X; b' N! {( g7 C6 T1 F6 g0 g

    ; K5 N# l- l4 |% @% X  d  T
1.1 详细介绍
HSI(内部高速时钟)
  • 它是RC振荡器,频率可以达到8MHZ,可作为系统时钟和PLL锁相环的输入
    / ]7 Q" E) L3 @4 S# z2 U2 ^
HSE(外部高速时钟)
  • 接入晶振范围是4-16MHZ,可作为系统时钟和PLL锁相环的输入,还可以经过128分频之后输入给RTC。

    + A7 ~" K) Q6 }; b' ?
LSI(内部低速时钟)
  • 它是RC振荡器,频率大概为40KHZ,供给独立看门狗或者RTC,并且独立看门口只能依靠LSI作为时钟源

    / E5 S4 m- o; k! I
LSE(外部低速时钟)
  • 通常外接32.768MHZ晶振提供给RTC

    2 Y7 G+ s& P- x0 D) ^* a* s5 Q4 |/ R
PLL(锁相环)
  • 用来倍频输出。因为开发板外部晶振只有8MHZ,而STM32最大工作频率是72MHZ。他可以通过HSI输入,HSE输入或两分频输入,通过PLL倍频(2-16),倍频之后输入给系统时钟。

    7 y3 u! z$ k6 I1 F6 m1 T
MCO(时钟输出管脚)
  • 通常对应STM32 PA8,它可以选择一个时钟信号输出,给外部的系统提供时钟源
    $ L; ~1 D8 N8 j& [1 m  @% d
2. 标准库的时钟配置2.1 stm32启动文件
首先打开startup_stm32f10x_hd.s,该文件为stm32的启动文件,在该文件内会发现有这么一块用汇编写的代码。
      Reset_Handler   PROC
/ w: T+ s0 ~* K# ?1 j9 n* f            EXPORT  Reset_Handler    [WEAK]
' z0 T) m$ u; Y5 n0 Q3 v' \            IMPORT  __main
) t3 F1 z( }8 C            IMPORT  SystemInit
2 u$ \0 A' X+ b* z% |+ E, ^            LDR     R0, =SystemInit) |/ _' O* C+ R0 d. h
            BLX     R0               
" ?+ Y3 m' w( J! ^            LDR     R0, =__main$ h8 s5 M' n+ ]% h+ I" O
            BX      R0
- U$ N" Q5 W! f2 k8 o$ s# [& a            ENDP
6 H% I' [0 ]6 o$ ?: F
通过这段汇编代码可以看出,程序在执行main函数之前,会先执行SystemInit函数。
2.2 SystemInit函数详解void SystemInit (void)
- Z) }# s! v: ]. _
{' m- _6 O" C& ^: ?- a+ G  B
  /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
! \1 Q$ Z" T/ r1 P  /* Set HSION bit */# M; _7 e2 u. l8 p( J- T! B
  RCC->CR |= (uint32_t)0x00000001;
5 w, D0 {9 H7 M$ z1 l7 @
$ w+ A0 \! c  w- P, O/ s/ ]  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */6 ]+ a. j. t1 E4 \. ?* s
#ifndef STM32F10X_CL
9 m( Q" n" P% k$ |& k/ B  RCC->CFGR &= (uint32_t)0xF8FF0000;& ^4 \8 P8 B8 H- M- v
#else
2 i8 T9 t, U. l' r9 n/ j7 A  RCC->CFGR &= (uint32_t)0xF0FF0000;- @5 m- m& |' ~1 w
#endif /* STM32F10X_CL */   
3 u2 [: B' ], u/ w. g! N0 Y* H! a9 n+ u+ s
  /* Reset HSEON, CSSON and PLLON bits */
+ u; e2 ^1 n- o- ^* l( C. S0 D  RCC->CR &= (uint32_t)0xFEF6FFFF;
! B& x0 O8 m; C3 \( F
1 b: I# h7 i8 i: A+ N; _1 ?  /* Reset HSEBYP bit */2 e5 A4 _# n% k* l, X
  RCC->CR &= (uint32_t)0xFFFBFFFF;$ _- L' q) [# ?8 S! Q

) v- P0 |! ?  Y. X. I  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
6 E6 a+ k. p  U& s  RCC->CFGR &= (uint32_t)0xFF80FFFF;
! }; W$ U8 a' ^5 d* F* f5 R  o1 _5 I4 m8 `8 x
#ifdef STM32F10X_CL
- B  r* G8 ?- c! Q  /* Reset PLL2ON and PLL3ON bits */
6 f" A' X4 x! C! K- t  RCC->CR &= (uint32_t)0xEBFFFFFF;$ u8 b+ z5 i0 m* _. ]" f

3 k5 ^; v% {6 A! r3 d& M# \3 M' C  /* Disable all interrupts and clear pending bits  */+ ^3 i+ ~. k& l
  RCC->CIR = 0x00FF0000;
$ c9 }$ e/ f- ~: g. [: f8 q% }. I2 b- b- X
  /* Reset CFGR2 register */
5 B/ _( ~% N5 L& K  RCC->CFGR2 = 0x00000000;
3 G) B& q! ]' ?7 R6 `#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
- t) _: w9 l& q" Z9 X) E5 ~  /* Disable all interrupts and clear pending bits  */
/ U. s  [; H# ~8 A  RCC->CIR = 0x009F0000;8 d3 c  h8 v9 p6 a& o/ F; ]
2 r7 w% m. ~; L
  /* Reset CFGR2 register */
* Y$ M/ R" @0 B& m: k, D( @  RCC->CFGR2 = 0x00000000;      / p8 w! R- n5 C- M* `  b
#else
3 v" d' ~0 f+ k% ~* C$ \9 A  /* Disable all interrupts and clear pending bits  */: d! U" C1 M( x( h' A4 B1 Y# L) q5 J$ g
  RCC->CIR = 0x009F0000;' s( Q: X8 V/ l; x7 z6 l, \: I
#endif /* STM32F10X_CL */, l) d: t+ D' J* E- z% [
) l4 }. a6 I  L# Y# F4 C
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
$ X8 t; y. C; ?- Z& t. Q- b  #ifdef DATA_IN_ExtSRAM
+ ^# y; t/ M$ j    SystemInit_ExtMemCtl(); 5 L- K* |! l3 d, F
  #endif /* DATA_IN_ExtSRAM */
; b; o) Q' B" X' i) h! h3 \9 b#endif " R# W2 o7 }. ^/ F8 o" u

3 V% l( X; {9 |  /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */! [. k) A4 o; b) d
  /* Configure the Flash Latency cycles and enable prefetch buffer */
4 w$ i7 Z; X1 k! Z/ z7 ]- f/ W. k  SetSysClock();
5 R* X# t" G" l: c- z4 c0 H0 P3 y0 V
#ifdef VECT_TAB_SRAM
9 o/ Q3 t& W  J! j( ~  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
: U+ J# e  A1 A/ b/ @) C#else# @0 W9 p+ k3 j" `$ p, B
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
9 v+ Z, T" c* O7 L+ H% o* P: @7 H#endif * L& E9 n3 L- k# a$ E( g
}% u( s! s9 q: W# X( h
打开内部8M时钟RCC->CR |= (uint32_t)0x000000018 D) \! |' t0 Y. A$ i
通过查看寄存器手册可知,这段代码为打开内部8M时钟。  f! U( ?, q/ F) Z7 j  f
微信图片_2025-12-04_151917_365.png
0 G9 J5 Y( `5 z. G设置时钟配置寄存器#ifndef STM32F10X_CL
$ B/ Y6 m! l$ j  RCC->CFGR &= (uint32_t)0xF8FF0000;
9 Y" Z' L( x$ M8 s# F1 w#else
) Q: S+ H- B7 x; @6 W  RCC->CFGR &= (uint32_t)0xF0FF0000;( a' ~4 i0 }) n. u4 |' w
#endif /* STM32F10X_CL */   
# V, ~+ q& [1 M) E- `  s
对应寄存器说明可查看《STM32中文参考手册_V10》的6.3.2 时钟配置寄存器(RCC_CFGR)章节。
后续代码,有兴趣可根据《STM32中文参考手册_V10》手册,查看代码具体作用。
2.3 SetSysClock()函数详解static void SetSysClock(void)
# d" R( j) J6 z6 G
{
& I7 h8 X2 F: {: g% _+ }#ifdef SYSCLK_FREQ_HSE
! K8 N1 B2 d0 \# d) f  SetSysClockToHSE();; O4 b/ J% K# z) g0 ^
#elif defined SYSCLK_FREQ_24MHz
) f8 A0 X4 @7 \0 b! c& r  SetSysClockTo24();+ B5 k* Q1 i0 S5 U, t6 X5 T
#elif defined SYSCLK_FREQ_36MHz
) R( Y* N9 x8 k1 Q  SetSysClockTo36();2 l. b: j5 M$ g/ W: r2 m5 |
#elif defined SYSCLK_FREQ_48MHz
, y, \, U' x: n& |1 a1 \  SetSysClockTo48();
: Q9 u! r% i5 T. |#elif defined SYSCLK_FREQ_56MHz
) R. W0 b( X3 o; T  SetSysClockTo56();  
: {7 I1 C5 {) s" E& m#elif defined SYSCLK_FREQ_72MHz, Q" e8 j$ W6 h, F! d
  SetSysClockTo72();* c6 q3 s9 r! d0 B' t/ R
#endif
6 j* r" O* [- c$ ~6 i}1 m/ G! w2 u1 N2 D
system_stm32f10x.c文件中会根据芯片的型号定义对应的宏
#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
4 H! E/ A6 R3 L2 ~/* #define SYSCLK_FREQ_HSE    HSE_VALUE */
: V% d& c9 w% R9 i: a1 l0 N* A #define SYSCLK_FREQ_24MHz  24000000
& O5 {9 W" G6 B1 G( @5 l9 s+ t#else
/ H5 y( N6 O7 V/ J0 K6 t/* #define SYSCLK_FREQ_HSE    HSE_VALUE */- K1 C+ w* L6 F# l2 U3 U7 P
/* #define SYSCLK_FREQ_24MHz  24000000 */ - a# H; q; Q/ A; d7 w- W
/* #define SYSCLK_FREQ_36MHz  36000000 */
6 s9 S, r4 k4 m0 f5 h$ P! q/* #define SYSCLK_FREQ_48MHz  48000000 */
: Y+ @" i+ o& s' h3 _6 G/* #define SYSCLK_FREQ_56MHz  56000000 */
4 L1 G+ ]* k% Q. t#define SYSCLK_FREQ_72MHz  72000000. E# E8 G) H: B# W
#endif
6 A8 [0 q7 D' d* g4 k6 N3. 时钟配置函数3.1 时钟初始化配置函数void SystemInit(void);
4 @6 M# \6 s3 M; B6 f/ Z1 }SYSCLK(系统时钟)=72MHZ;, F- I. Q6 s( p  L6 V6 }  G1 @6 S0 M
AHB总线时钟(HCLK=SYSCLK)=72MHZ;
  B: x1 O) l* u, [APB1总线时钟(PCLK1=SYSCLK/2)=36MHZ;9 W* U' @" K; _
APB2总线时钟(PCLK1=SYSCLK/1)=72MHZ;; F2 l9 ?9 b. p: M3 ]: n: E
PLL主时钟=72MHZ;2 F9 U+ l* A* k+ m2 f: d
3.2 外设时钟使能配置函数void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);! [# c) |% t$ C
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);; d1 i. U: d9 _
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);+ A! a0 q$ j! o, R% ?
3.3 时钟源使能函数void RCC_HSICmd(FunctionalState NewState);
- S" b2 M4 l" Z! j4 w+ vvoid RCC_LSICmd(FunctionalState NewState);4 T& Z6 Y. |: [% H8 S' w/ s, b: G8 T; l; B
void RCC_PLLCmd(FunctionalState NewState);+ m: _/ r, D( d8 M
void RCC_RTCCLKCmd(FunctionalState NewState);
8 B5 u3 Y4 N" B6 s% ~/ w8 }2 P3.4 时钟源和倍频因子配置函数void RCC_HSEConfig(uint32_t RCC_HSE);
' w, w7 x0 q) Z5 y" h5 avoid RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);$ y0 o, n" j3 i, y
void RCC_HCLKConfig(uint32_t RCC_SYSCLK);4 D" M) u- \. C" u
void RCC_PCLK1Config(uint32_t RCC_HCLK);
- r1 f! W6 j: \1 M$ hvoid RCC_PCLK2Config(uint32_t RCC_HCLK);/ y  [- ^. {; A+ }7 _$ \  l
3.5 外设时钟复位函数void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);& G8 A& J+ \& l; L0 J
void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);* s0 C& k1 x0 p) U1 a
3.6 自定义系统时钟void RCC_HSE_Config(u32 div,u32 pllm)$ W" k1 z+ n0 c4 `" n7 x5 _
{0 z  u7 f6 |& _* K  y+ @
    RCC_DeInit();
4 N- W) x! g* o2 n8 r    RCC_HSEConfig(RCC_HSE_ON);: B- X" v9 x) \2 {0 k; V; h
    if(RCC_WaitForHSEStartUp()==SUCCESS)! ~5 s% s5 k; B, ?3 Z
    {   
. x1 g, u/ Y" ?* {$ I* V3 ^. x        RCC_HCLKConfig(RCC_SYSCLK_Div1);
! U1 o0 c5 E  V- C# S        RCC_PCLK1Config(RCC_HCLK_Div2);
( b, a# c# l! l! J  ?; P        RCC_PCLK2Config(RCC_HCLK_Div1);
5 r, O8 j! A# o$ w        RCC_PLLConfig(div,pllm);/ A  b) h1 k9 H" v4 q1 ^) |
        RCC_PLLCmd(ENABLE);     
- l& b( w5 F# O9 j$ N: V    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)6 g  _4 y2 }! r7 o! R
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK)* o% @/ f# x  K# q& Q' ]; S. W
    while(RCC_GetSCLKSource()!=0x08);
3 K$ L) R; f9 H- V) Y7 F3 s, N, f5 c! E# L( w
    }+ U% g5 R* G) o9 c5 E
}
: W0 T- \# x' U- z7 [
赞 收藏 评论0 发布时间:2025-12-4 15:21

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版