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

基于STM32时钟系统经验分享

[复制链接]
攻城狮Melo 发布时间:2023-11-4 19:02
1 STM32的时钟源主要有:! V, x1 g: @8 c. q
内部时钟
/ }- _" }! y5 o: ~9 H* p) ^5 I: ~外部时钟3 ~% H% x# o9 i4 l
锁相环倍频输出时钟; i2 s  ]* k! {7 c: u" n+ N
微信图片_20231104190126.png

' q. s  ], m+ K
( A. q* i# I  K1 E4 i3 ]& U1.1 详细介绍

( }* W% W( r/ C0 C; }5 ZHSI(内部高速时钟)" p' h& u" g& K% q+ |9 Q
它是RC振荡器,频率可以达到8MHZ,可作为系统时钟和PLL锁相环的输入) a/ Z1 t& ~; o- e- g; N
+ R" Q5 O$ `+ [- U3 S
HSE(外部高速时钟)
9 f4 r; n/ r; S+ C  R+ z接入晶振范围是4-16MHZ,可作为系统时钟和PLL锁相环的输入,还可以经过128分频之后输入给RTC。3 E" s7 O+ R1 ~. u1 v
: j- o; ?* c( u( q" i1 c0 ]1 o
LSI(内部低速时钟)
: Q1 X9 F5 k- g  r" H3 d它是RC振荡器,频率大概为40KHZ,供给独立看门狗或者RTC,并且独立看门口只能依靠LSI作为时钟源
* @: @' [1 N3 @5 d8 a* F8 M6 M. r1 Q. e( C
LSE(外部低速时钟)
9 v% `" W0 a$ u! \6 L; l! K0 E通常外接32.768MHZ晶振提供给RTC
/ |7 n# W7 j5 p% I; m5 ~! e3 S9 X+ T& R; ?+ j
PLL(锁相环)/ m. J6 X9 J! ^* Y
用来倍频输出。因为开发板外部晶振只有8MHZ,而STM32最大工作频率是72MHZ。他可以通过HSI输入,HSE输入或两分频输入,通过PLL倍频(2-16),倍频之后输入给系统时钟。% h7 `' C& ?1 K

* V3 F* F' n: u5 L* z" v9 |) r7 K
MCO(时钟输出管脚)4 e8 M2 d1 r) }5 G9 U
通常对应STM32 PA8,它可以选择一个时钟信号输出,给外部的系统提供时钟源
: m6 i% |+ t8 B' T! R! \5 g
3 ]2 w3 U, {1 A! I( [
2 标准库的时钟配置
# C: H3 i0 j) ^' [. F) B  X# E3 ~2.1 STM32启动文件
5 i: l0 d  f  V2 p1 L( S
首先打开startup_stm32f10x_hd.s,该文件为stm32的启动文件,在该文件内会发现有这么一块用汇编写的代码。
9 r1 h, b! u/ X: ~& J
  1.       Reset_Handler   PROC2 h; O. g: W2 U8 x
  2.             EXPORT  Reset_Handler    [WEAK]  X5 q  V! v& S3 n
  3.             IMPORT  __main0 _" O3 }$ B4 X( [& Q2 d
  4.             IMPORT  SystemInit
    ; p0 [  q1 C& t+ H' |
  5.             LDR     R0, =SystemInit, B' ^2 |) e2 W# |: y8 ^
  6.             BLX     R0               
    6 U( l# g' b, k! g; {
  7.             LDR     R0, =__main
    6 O) f5 Q7 g+ X4 X
  8.             BX      R0
    1 ?( F' K: W* A  f4 }7 D
  9.             ENDP
复制代码
: A8 z# K2 W" p0 G
通过这段汇编代码可以看出,程序在执行main函数之前,会先执行SystemInit函数。+ e# m. l6 o* {, [, |' g+ s

) X' c! R. v" P0 j! A) L% _  P
2.2 SystemInit函数详解
  1. void SystemInit (void)
    . x7 U! {7 V! m( U5 h6 b
  2. {
    , R& p( x! x1 Q4 K5 p5 q* z6 M
  3.   /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
    " Z( Z* [4 t4 V: A
  4.   /* Set HSION bit *// j! [+ Y. Q2 }- `8 p4 k
  5.   RCC->CR |= (uint32_t)0x00000001;
    0 C6 a- I7 l$ K( o
  6. 6 [+ O+ w+ V. }+ Y* E
  7.   /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */$ N$ v! o* s' t4 M6 i
  8. #ifndef STM32F10X_CL( N) q9 l$ Q# u) N4 W' m2 c: J) }
  9.   RCC->CFGR &= (uint32_t)0xF8FF0000;
    9 V" F6 J% G3 e) N. L- r
  10. #else. I4 c8 u! o+ O# L5 N
  11.   RCC->CFGR &= (uint32_t)0xF0FF0000;1 s% ]; k$ O0 Y; H/ A  }2 ~+ N
  12. #endif /* STM32F10X_CL */   9 D. }* n# ^$ a) ~7 d( h
  13. 8 H! d6 a+ T  ]; j
  14.   /* Reset HSEON, CSSON and PLLON bits */  p/ y$ D  @% V0 U, c) s" \
  15.   RCC->CR &= (uint32_t)0xFEF6FFFF;  ?3 d( M! b; C9 j1 V9 V

  16. 8 p* N. R( a6 f. [7 d$ I
  17.   /* Reset HSEBYP bit */: \. J, ^( U5 N( _0 B& L/ V* q3 t
  18.   RCC->CR &= (uint32_t)0xFFFBFFFF;
    ! X5 g: L  k& B% q5 i$ Z" f
  19. : k7 Z% R3 Z, x) L5 q, A; T& B* ^$ N
  20.   /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */2 f9 |. D3 E; b% d" \
  21.   RCC->CFGR &= (uint32_t)0xFF80FFFF;! ]$ a0 X+ K9 y, K+ R
  22. % z$ l3 ^* w; r+ r6 C& @* w
  23. #ifdef STM32F10X_CL2 b$ C2 ^+ w$ K& _$ `
  24.   /* Reset PLL2ON and PLL3ON bits */( n2 J+ }- t# W% u: ?
  25.   RCC->CR &= (uint32_t)0xEBFFFFFF;. Y6 c: @% T# O% J$ z1 {
  26. $ D1 x# G# _3 P5 L- f$ z
  27.   /* Disable all interrupts and clear pending bits  */0 t( V+ o$ x) W8 x. m( p$ t8 O
  28.   RCC->CIR = 0x00FF0000;
    , P& `& b  t) v0 u; N6 J3 S: O: p5 f
  29. . _! @: g6 g; f: R) y% S3 m! s9 y
  30.   /* Reset CFGR2 register */! B  ~) O. x* k
  31.   RCC->CFGR2 = 0x00000000;
    ) g  k* V. k' n2 Q  `* i" b
  32. #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
    9 V( i6 A+ Y# }2 W
  33.   /* Disable all interrupts and clear pending bits  */
    : m+ t/ P( I) g8 g
  34.   RCC->CIR = 0x009F0000;
    " M9 ], f, ?2 |. `5 Q

  35. ' x+ s( k5 T6 T0 V, e- y
  36.   /* Reset CFGR2 register */
    / j% f) q0 [4 H9 y2 d7 u
  37.   RCC->CFGR2 = 0x00000000;      
    : ~5 d$ c9 g1 i4 B
  38. #else- w* l9 i8 K- M
  39.   /* Disable all interrupts and clear pending bits  */5 A0 N& T+ B0 m& U9 H2 R& v( {$ w
  40.   RCC->CIR = 0x009F0000;
    ( A, k$ x, G/ L
  41. #endif /* STM32F10X_CL */
    " t: U7 e6 a, i' @& ^

  42. 5 T& j% ?( X4 w, j. j/ ~% s" ^
  43. #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
    ' h2 O2 b2 Q2 u- ^: b$ O* T
  44.   #ifdef DATA_IN_ExtSRAM/ n' R) G  l8 z  X1 _. ]% A- K
  45.     SystemInit_ExtMemCtl(); + H, B6 R5 Q8 W6 u9 ~+ O% Y5 I# Z
  46.   #endif /* DATA_IN_ExtSRAM */: l9 Z2 E2 g/ i% U2 @* b
  47. #endif 9 g/ V, ^; T" X( [1 Q7 H8 ^
  48. 3 l" E8 v1 D5 n
  49.   /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
    % r0 v- z+ L  T/ P/ e$ c
  50.   /* Configure the Flash Latency cycles and enable prefetch buffer */
    1 N# c$ _( W3 U( F8 {
  51.   SetSysClock();! H7 I8 M* m" \' T; [

  52. : E2 }& I: `# Q  t
  53. #ifdef VECT_TAB_SRAM
    5 X$ S) _5 O2 g3 o3 a' q
  54.   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
    ! \! X2 }, c' t$ @; p
  55. #else) n5 O3 B% G( \/ p  Z* ]8 h
  56.   SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */, A# S4 X0 v: Z+ u  s
  57. #endif # b( n8 |6 b) O$ }$ L7 m
  58. }
复制代码
4 r! E- k' [$ {; Q

" E& A, W8 v" r打开内部8M时钟:" K, Y$ Y/ ?# q" ]: @/ m1 a% R! x6 U
  1. RCC->CR |= (uint32_t)0x00000001
复制代码
' j- Y5 U$ J5 Y  O; K% n
通过查看寄存器手册可知,这段代码为打开内部8M时钟。6 t% C( E# l/ k- i% ?

; x4 r' G; y' U* v/ ?) G- ~0 A
微信图片_20231104190120.png
% y6 v& p0 i: a' E6 p: l

" o& b+ w  Q! Q* i9 Q3 A' p+ g5 V设置时钟配置寄存器:: l9 e- ?  f- N# _9 v
  1. #ifndef STM32F10X_CL. A% B( {: T+ X! B" H
  2.   RCC->CFGR &= (uint32_t)0xF8FF0000;' W! C+ z3 r( T) m( M
  3. #else4 ?7 B# v/ x5 d* S8 k" l
  4.   RCC->CFGR &= (uint32_t)0xF0FF0000;
    & Z2 x" R0 p  ]9 m: p( u
  5. #endif /* STM32F10X_CL */   
复制代码

$ e5 @- e( R/ n2 z+ x对应寄存器说明可查看《STM32中文参考手册_V10》的6.3.2 时钟配置寄存器(RCC_CFGR)章节。3 n% `' a! r% a/ \+ e
后续代码,有兴趣可根据《STM32中文参考手册_V10》手册,查看代码具体作用。
3 K& \0 t$ V: C. n+ W
9 p1 W$ c, _& F0 t# H& c6 a( e
2.3 SetSysClock()函数详解
9 Q* }8 a8 z& e4 A* V  h+ w" W
  1. static void SetSysClock(void)$ }& P& e/ {1 }! H: r4 q( `2 _
  2. {" r% n& s3 D' K" T
  3. #ifdef SYSCLK_FREQ_HSE! p" m: y) [  Y: s% |
  4.   SetSysClockToHSE();
    9 O7 i2 P3 l: [
  5. #elif defined SYSCLK_FREQ_24MHz, k: O% u+ W( z  \" w
  6.   SetSysClockTo24();. Y- E/ R5 O& `# u$ |1 j0 G  {! x
  7. #elif defined SYSCLK_FREQ_36MHz. T! `8 u. _6 \6 B8 U
  8.   SetSysClockTo36();3 B8 s( I" r  y& u
  9. #elif defined SYSCLK_FREQ_48MHz  u! [0 p' k% F3 j0 Z
  10.   SetSysClockTo48();
    ) V; N8 u$ J& Y9 J$ o+ ]
  11. #elif defined SYSCLK_FREQ_56MHz; \5 p/ |! [7 U# A" n
  12.   SetSysClockTo56();  % g, R) O9 L7 _1 n1 N
  13. #elif defined SYSCLK_FREQ_72MHz8 C+ X3 d+ g, ]7 g8 P
  14.   SetSysClockTo72();
    : c) E4 k9 P' O  z  a. b1 T- N
  15. #endif
    : M& j4 w8 E  m
  16. }
复制代码

! G+ |6 u# b7 P# j2 Y% U- ~( g0 d: _6 ^) ?1 W4 f
system_stm32f10x.c文件中会根据芯片的型号定义对应的宏:
& V& S/ i. d6 N+ @+ Y
  1. #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
    ; l/ k- a0 z0 a4 J, U, `
  2. /* #define SYSCLK_FREQ_HSE    HSE_VALUE *// u) V  Z" ?( Q) Z' K$ ?
  3. #define SYSCLK_FREQ_24MHz  24000000
    8 n% b/ A! u# D% u! `
  4. #else
    9 w) K) O5 A/ P$ X3 O
  5. /* #define SYSCLK_FREQ_HSE    HSE_VALUE */" ^$ X# U/ _( S. q2 e8 M
  6. /* #define SYSCLK_FREQ_24MHz  24000000 */ 7 o4 u, L$ Q  W3 r
  7. /* #define SYSCLK_FREQ_36MHz  36000000 */
    7 \  p3 s: f% A5 L+ R" E5 x
  8. /* #define SYSCLK_FREQ_48MHz  48000000 */
    $ Q9 |5 E. R  i1 y2 b
  9. /* #define SYSCLK_FREQ_56MHz  56000000 */# L8 b6 S% l  n% q8 G: r
  10. #define SYSCLK_FREQ_72MHz  72000000
    - Q7 P* ]6 @. P1 X* R
  11. #endif
复制代码
: k% M1 @" l. t  r) u- ]0 ]. X
3 时钟配置函数
* n+ t0 w  {' v  ?3.1 时钟初始化配置函数
  1. void SystemInit(void);
    8 M" f" @$ f1 D2 b+ m
  2. SYSCLK(系统时钟)=72MHZ;; E2 a" p& n7 r6 ^1 x4 F
  3. AHB总线时钟(HCLK=SYSCLK)=72MHZ;# |; P( r0 T8 n+ N7 [
  4. APB1总线时钟(PCLK1=SYSCLK/2)=36MHZ;, o2 M) p8 M4 D( y+ c6 j
  5. APB2总线时钟(PCLK1=SYSCLK/1)=72MHZ;
    ; @$ `  x8 J/ x8 e! |4 g
  6. PLL主时钟=72MHZ;
复制代码

. l* j- r4 J* B! _( o9 z* {6 S$ o/ L6 z2 [! W" e7 f$ I
3.2 外设时钟使能配置函数8 T2 W6 L3 Q0 l, p! |6 t" O
  1. void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
    " B9 q3 k) u. ]6 P
  2. void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);# m+ R+ @$ J$ {. f3 b; ?$ Q9 p
  3. void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
复制代码
. i% T' L# x1 a# F8 S9 n8 ]4 P
3.3 时钟源使能函数
  1. void RCC_HSICmd(FunctionalState NewState);
    - s  h+ d3 l% L! J0 t" e
  2. void RCC_LSICmd(FunctionalState NewState);# T2 g' z1 i( S6 Q
  3. void RCC_PLLCmd(FunctionalState NewState);$ d) B: G( f- _7 M6 F6 c  M
  4. void RCC_RTCCLKCmd(FunctionalState NewState);
复制代码

" O( t* c: O6 b9 j  U6 S
: Z4 X2 }5 @, k7 }, V3.4 时钟源和倍频因子配置函数
0 g' P9 e! R: p$ d, K- M0 y
  1. void RCC_HSEConfig(uint32_t RCC_HSE);
    + g+ ?7 Y4 g& C" `* i! }
  2. void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);
    ! j- O0 u! o2 W" G7 c+ Z
  3. void RCC_HCLKConfig(uint32_t RCC_SYSCLK);
    ' n2 H2 _$ H# `8 Z- n* P* u* k# B, K
  4. void RCC_PCLK1Config(uint32_t RCC_HCLK);
    7 Z1 a+ i5 R' ]( X& x
  5. void RCC_PCLK2Config(uint32_t RCC_HCLK);
复制代码

" u8 ]) E) w  b5 i6 o4 E" b' ~% `! u3.5 外设时钟复位函数" ^* [- @- G! b! G5 \  V
  1. void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);: w3 P& |# Z5 X
  2. void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
复制代码
  h9 Q8 u# Y0 P
3.6 自定义系统时钟! p+ X" {; |% Y3 f) U! x( q" G
  1. void RCC_HSE_Config(u32 div,u32 pllm)
    $ b4 N2 v% U* i+ S
  2. {
    % B" G, x5 |0 `5 ]% t
  3.     RCC_DeInit();
    7 l; R; o- ~% c" R' b
  4.     RCC_HSEConfig(RCC_HSE_ON);8 D; z# N4 \2 R
  5.     if(RCC_WaitForHSEStartUp()==SUCCESS)
    8 `* z+ i6 s  m
  6.     {   
    / S3 \7 Y1 q4 y
  7.         RCC_HCLKConfig(RCC_SYSCLK_Div1);. B/ s3 E' |: o0 m" ]
  8.         RCC_PCLK1Config(RCC_HCLK_Div2);& ~. r/ ]  n, q/ J0 Z" }* E6 Z$ W
  9.         RCC_PCLK2Config(RCC_HCLK_Div1);, q/ N' C5 [* U2 u$ ^, Q$ e
  10.         RCC_PLLConfig(div,pllm);, T4 N4 t% m5 f7 ]" |
  11.         RCC_PLLCmd(ENABLE);     : i. _7 B6 k2 C  g* j2 c
  12.     while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)4 R/ w& W" ~- ]  B" t- W* J
  13.         RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK)4 ?7 {: M, O! A- c, g( }" h: s. Z
  14.     while(RCC_GetSCLKSource()!=0x08);! ~% W' x4 W! S. j
  15. $ b; y8 j6 g1 {; {. e7 R  s4 i
  16.     }
    6 ?1 W- ~: `6 p- R5 `) S6 I) p# V8 z
  17. }
复制代码
转载自:STM32嵌入式开发6 I6 E  h8 {$ m' |. U8 m: K4 j
* y0 s7 p& T& E, p# a5 C: ^
如有侵权请联系删除  g/ y1 a& {- y' S1 o# Q& g
) |. g- g: y) O( O3 b7 m
赞 收藏 评论0 发布时间:2023-11-4 19:02

举报

0个回答

所属标签

相似技术帖

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