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

STM32时钟详解

[复制链接]
flyingstar 发布时间:2025-12-4 15:21
STM32时钟源介绍1. STM32的时钟源主要有:
  • 内部时钟
  • 外部时钟
  • 锁相环倍频输出时钟# e2 H" M! j. O2 s2 i# w! \
    640.png / `1 D' H- a( P; E7 K
    ; u& f5 M3 M' E1 u0 _2 U
1.1 详细介绍
HSI(内部高速时钟)
  • 它是RC振荡器,频率可以达到8MHZ,可作为系统时钟和PLL锁相环的输入
    - K4 ?1 S2 D0 A- o
HSE(外部高速时钟)
  • 接入晶振范围是4-16MHZ,可作为系统时钟和PLL锁相环的输入,还可以经过128分频之后输入给RTC。

    - V  F+ w& B  L$ L, j3 u% v
LSI(内部低速时钟)
  • 它是RC振荡器,频率大概为40KHZ,供给独立看门狗或者RTC,并且独立看门口只能依靠LSI作为时钟源
    1 v6 C2 S6 }" `" i
LSE(外部低速时钟)
  • 通常外接32.768MHZ晶振提供给RTC
    & x; Y8 `% h8 `9 y
PLL(锁相环)
  • 用来倍频输出。因为开发板外部晶振只有8MHZ,而STM32最大工作频率是72MHZ。他可以通过HSI输入,HSE输入或两分频输入,通过PLL倍频(2-16),倍频之后输入给系统时钟。
    + J% i( {5 C: I. [  b
MCO(时钟输出管脚)
  • 通常对应STM32 PA8,它可以选择一个时钟信号输出,给外部的系统提供时钟源
    2 }) L$ n9 m( q
2. 标准库的时钟配置2.1 stm32启动文件
首先打开startup_stm32f10x_hd.s,该文件为stm32的启动文件,在该文件内会发现有这么一块用汇编写的代码。
      Reset_Handler   PROC* c' w- n. _$ ]5 C6 b- A' t
            EXPORT  Reset_Handler    [WEAK]
( |1 Y+ I2 G+ t: c* Z            IMPORT  __main
8 D1 A+ v7 J6 P( v% @; Y            IMPORT  SystemInit
# p) e8 G( g  l9 S: X5 L4 J7 W            LDR     R0, =SystemInit
8 Q2 I% p# A& C            BLX     R0               8 i# D& k6 q; g
            LDR     R0, =__main' `: ~5 Q( i2 S, A  F
            BX      R0
9 L' M( d+ D* X$ A            ENDP
  t6 e7 E* G  I# e( P+ C; W
通过这段汇编代码可以看出,程序在执行main函数之前,会先执行SystemInit函数。
2.2 SystemInit函数详解void SystemInit (void)
3 ^; e0 n4 e2 y, Y; K. j0 K" V
{% r0 ?  G( P, k, h  x
  /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  _& ~- P; V( Q  /* Set HSION bit */2 `8 w; v% e2 v9 Q4 x
  RCC->CR |= (uint32_t)0x00000001;
( k% G; q) g- {5 [0 F8 J. J, ]4 f0 Z+ [$ i" W3 t
  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */  O: r# v' l! ?( V
#ifndef STM32F10X_CL2 Z- v9 h% P' ]& i2 R, J( t
  RCC->CFGR &= (uint32_t)0xF8FF0000;
1 c- d, Q5 V' X7 p5 p* ]. p#else
* H9 F/ e2 M1 M. t# f7 b  RCC->CFGR &= (uint32_t)0xF0FF0000;; Y  `: ^& K! m1 Y. e2 w/ }
#endif /* STM32F10X_CL */   
  S6 y9 y9 w. Q0 \
/ I" W0 G% `* K, @' E8 ]$ C  /* Reset HSEON, CSSON and PLLON bits */& T8 k3 o" X$ T" Y( h
  RCC->CR &= (uint32_t)0xFEF6FFFF;
) [  @" E% d4 A/ \9 ?6 M8 q# s6 p, Y4 O( V# V) r
  /* Reset HSEBYP bit */
7 Y5 t3 d, J) T2 w  q2 ^  RCC->CR &= (uint32_t)0xFFFBFFFF;
2 k/ {% i" u  j7 O+ K3 f; W5 X; X* |. r9 O2 |/ c. n7 q( u$ f9 m% F
  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */" O* I8 r+ k3 m3 c& p
  RCC->CFGR &= (uint32_t)0xFF80FFFF;4 n6 E; j' e, p* y& {$ O5 F" e

. S4 r9 Y! T8 S5 ]#ifdef STM32F10X_CL0 q7 M; p+ l- O+ \
  /* Reset PLL2ON and PLL3ON bits */! Q& D4 g, v8 e: C5 M/ q, W
  RCC->CR &= (uint32_t)0xEBFFFFFF;: L; _' g6 k* c  _/ v

( s$ E% |' C; q  L  /* Disable all interrupts and clear pending bits  */9 v' y% ~. N: u, M8 K/ Q/ y6 t
  RCC->CIR = 0x00FF0000;
5 A  k1 ~1 G- k% a
7 Z/ ?2 y3 X9 S, r$ i  /* Reset CFGR2 register */
) v, O2 {3 z6 w0 o6 M- j  RCC->CFGR2 = 0x00000000;, u( ]& ^* p  _/ H+ ?1 i
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL); w& E* v( z$ P/ q
  /* Disable all interrupts and clear pending bits  */
+ }: W/ N$ I/ s  w% m; C4 T  RCC->CIR = 0x009F0000;
6 V4 r; Q/ Q$ W% H" {; h& _( a2 C; r
  /* Reset CFGR2 register */
" v7 C4 s/ m  g* y: t  RCC->CFGR2 = 0x00000000;      
' q/ {8 r/ |6 S' w+ d#else
, N" S8 z* J0 y  /* Disable all interrupts and clear pending bits  */
) N% @) Z) O; _* {  x* W! n  RCC->CIR = 0x009F0000;+ }- b7 R. a# P8 Z& \6 t. ^
#endif /* STM32F10X_CL */" X& L* V: N6 U- C7 g3 _

/ y& F# X. T. `5 c#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL), Z0 W# W% k+ w1 |' \& i$ c
  #ifdef DATA_IN_ExtSRAM4 a8 ~% W* R( O0 U; e- d4 z% c3 m
    SystemInit_ExtMemCtl(); % j; l* r% e1 C/ x' {9 A
  #endif /* DATA_IN_ExtSRAM */
% {* Z9 g/ Y0 F, p% @7 @9 F#endif . Q, F# P. f/ e

& {& F. \4 h7 M, Y  Q0 K5 ?  /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */: j- K' z; T/ t) W3 S) A
  /* Configure the Flash Latency cycles and enable prefetch buffer */
0 y. |6 D7 h( @# ?  SetSysClock();
7 U! y3 @; R2 D6 F9 x- }7 G* K9 w5 c) I  {$ S, v' w* t( [, b5 n  I
#ifdef VECT_TAB_SRAM. O# g8 A" D7 {: z9 h
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
3 n0 x  v# u! z7 D#else& @1 x& Y, g+ e' u% Q, ]- |
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */* }( x- d- q! f
#endif , |# o& N/ [6 \) G" w/ s
}
, z3 v- I, @. ~6 ^: M打开内部8M时钟RCC->CR |= (uint32_t)0x00000001
, O. p1 f' [" K2 i/ b
通过查看寄存器手册可知,这段代码为打开内部8M时钟。
1 h* H# t6 }4 e; Y, ^; j
微信图片_2025-12-04_151917_365.png ( R7 W# j* o2 H. G4 e6 {
设置时钟配置寄存器#ifndef STM32F10X_CL% u6 `# h1 d4 B/ M
  RCC->CFGR &= (uint32_t)0xF8FF0000;
% e' N$ F5 d% N: W2 C#else; M2 d+ t; F+ y3 w2 ?8 O( I
  RCC->CFGR &= (uint32_t)0xF0FF0000;/ G6 J3 k$ \' ]$ P9 q
#endif /* STM32F10X_CL */   
- g) H0 W; j% I9 F* {6 E! D
对应寄存器说明可查看《STM32中文参考手册_V10》的6.3.2 时钟配置寄存器(RCC_CFGR)章节。
后续代码,有兴趣可根据《STM32中文参考手册_V10》手册,查看代码具体作用。
2.3 SetSysClock()函数详解static void SetSysClock(void); S* o) N* f$ T% r
{
$ P2 P+ {& Y% A; \5 m; G4 T% R#ifdef SYSCLK_FREQ_HSE
8 _$ O! R2 y, s0 Y0 e* w, E: w  SetSysClockToHSE();
* X: [; p/ |3 x#elif defined SYSCLK_FREQ_24MHz
; H6 }4 W; N" X% u; o- m  SetSysClockTo24();0 V" h% t4 m6 L! @5 Y, Z% \  A9 i# Z
#elif defined SYSCLK_FREQ_36MHz0 a. C0 a. f3 q
  SetSysClockTo36();4 W6 }2 Y4 l& X9 `
#elif defined SYSCLK_FREQ_48MHz
+ T. C9 [6 w8 }; h$ F# T2 P  SetSysClockTo48();( \) V3 |3 r3 g9 U/ V5 `( r) c
#elif defined SYSCLK_FREQ_56MHz
! N/ K  `2 L$ p' R- s  SetSysClockTo56();  ; i/ _# q. T" z! f1 h( j! J
#elif defined SYSCLK_FREQ_72MHz3 ~# j1 N  Z& h
  SetSysClockTo72();, L. m/ z0 d. ?4 _) O# S* W: A
#endif
8 A) g4 Y+ x- w- |* T}
6 y- C7 N) e2 `
system_stm32f10x.c文件中会根据芯片的型号定义对应的宏
#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
8 ^3 u9 q% t; N% p* B/* #define SYSCLK_FREQ_HSE    HSE_VALUE */
( v3 {9 h- v* ^9 C& u  U: b# E #define SYSCLK_FREQ_24MHz  24000000
/ U1 ]! n4 W. H% z$ D3 I#else! Q; q' V% P. [2 R/ g+ B- B
/* #define SYSCLK_FREQ_HSE    HSE_VALUE */7 a7 I, ^- Y) u- Q
/* #define SYSCLK_FREQ_24MHz  24000000 */
0 Y2 Y" W/ V6 R# y+ u: ~% [/* #define SYSCLK_FREQ_36MHz  36000000 */
5 x+ `# _# a9 G/ Z/* #define SYSCLK_FREQ_48MHz  48000000 */
6 l, a( j3 h7 l2 X  ]  x. R# O& H/* #define SYSCLK_FREQ_56MHz  56000000 */
$ J  n2 l2 Z1 x4 U4 i6 b# g#define SYSCLK_FREQ_72MHz  720000003 r' E9 H& U: l4 R3 J
#endif
; ?# J+ r. Q: s. s) |# c# o3. 时钟配置函数3.1 时钟初始化配置函数void SystemInit(void);, {1 p" r( G% Z6 F
SYSCLK(系统时钟)=72MHZ;
$ ^& d; Z9 g1 ]6 `/ m9 ^2 lAHB总线时钟(HCLK=SYSCLK)=72MHZ;/ C; E& K5 }& ?- g* P! J
APB1总线时钟(PCLK1=SYSCLK/2)=36MHZ;: m* {: Y! M' ~
APB2总线时钟(PCLK1=SYSCLK/1)=72MHZ;7 |4 E  u& ^, ~7 p1 A# V
PLL主时钟=72MHZ;
" m9 p8 y0 ?) Q9 H8 w1 j3.2 外设时钟使能配置函数void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);. A1 \  o' {9 g
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
# h8 P( U% F9 ], n0 b9 evoid RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
, G; y4 G, [- ]3 P- D3.3 时钟源使能函数void RCC_HSICmd(FunctionalState NewState);, {2 S/ c# P7 f% ?- \2 I
void RCC_LSICmd(FunctionalState NewState);
: {7 n0 u8 p+ T6 \2 n5 q! rvoid RCC_PLLCmd(FunctionalState NewState);+ b0 S5 q) C/ c. j; x/ e2 i. n, s
void RCC_RTCCLKCmd(FunctionalState NewState);
. Z2 Z* E" X" G% _9 ^* l" N& u3.4 时钟源和倍频因子配置函数void RCC_HSEConfig(uint32_t RCC_HSE);
9 b4 v1 u2 J' o! j0 e" bvoid RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);2 w4 E% z. o" i4 M8 C2 r
void RCC_HCLKConfig(uint32_t RCC_SYSCLK);* q/ B( I) Z, x3 Y% [
void RCC_PCLK1Config(uint32_t RCC_HCLK);
8 Z/ u  t0 r& z* z9 d; X$ u0 |void RCC_PCLK2Config(uint32_t RCC_HCLK);5 h. a& n. f+ b; B5 q2 c
3.5 外设时钟复位函数void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);; u: s  o7 [" y7 z! L- T$ B5 x& Y
void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
2 f% }: D: T/ M3.6 自定义系统时钟void RCC_HSE_Config(u32 div,u32 pllm)
# {/ `2 z* k7 [2 T
{
% B0 V# @( y4 W+ Q3 q/ C. W    RCC_DeInit();
' I$ N- {  X$ y" L0 e% b    RCC_HSEConfig(RCC_HSE_ON);* q. V1 ]% t1 Q
    if(RCC_WaitForHSEStartUp()==SUCCESS)4 n9 F, c" ^9 R0 `9 a
    {   
3 c8 `4 c6 {5 |& f* S: Y" S4 |        RCC_HCLKConfig(RCC_SYSCLK_Div1);5 Q- I) n2 l( r( a  B4 o
        RCC_PCLK1Config(RCC_HCLK_Div2);6 E! ?6 ]0 ^" X) B( v
        RCC_PCLK2Config(RCC_HCLK_Div1);2 a6 B5 Z9 o% W( l2 \
        RCC_PLLConfig(div,pllm);! l) k- y. N3 g3 {- a# R( C  p, n4 ?
        RCC_PLLCmd(ENABLE);     5 S( q1 _) t( n; Q
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)
  z; g+ w, ]) R! `( h        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK)
7 B) b/ g) N4 v3 d* |7 y    while(RCC_GetSCLKSource()!=0x08);
0 X, ]. ~$ T& H) O3 W9 e* L& P) b* V4 l
5 C9 k( W4 \. P    }, q3 Z- d8 t4 k; X, U
}
: v$ m0 Y3 o  E2 t" l3 F  ]8 K3 _. B
赞 收藏 评论0 发布时间:2025-12-4 15:21

举报

0个回答

所属标签

相似技术帖

官网相关资源

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