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

【经验分享】关于CotexM3和的STM32F103系列的时钟理解及配置

[复制链接]
STMCU小助手 发布时间:2022-3-16 10:57
现附上我自行实现的时钟配置函数9 f8 x5 v: Z* N
3 C- L! i) ], M* B  E5 c% l
  1. //RCC_PLLSource:PLL时钟源
    4 y9 G/ ~  y* r/ j$ Z. a
  2. //RCC_PLLSource_HSI_Div2、RCC_PLLSource_HSE_Div2、RCC_PLLSource_HSE_Div1- y+ j& h3 E: b) a. ~! r6 A3 L. W
  3. //PLLMUL:PLL输入时钟的倍频系数 范围RCC_CFGR_PLLMULL2~16
    ! [) l9 y$ h6 Z8 _. v- x
  4. //PLL时钟根据时钟和倍频来确定,选择内部时钟最高64M
    - z  S0 D! m. V/ e
  5. void SysClock_Configuration(uint32_t RCC_PLLSource, uint32_t PLLMUL)
    9 ~# c8 m8 {' Y" c- V7 V. s
  6. {( O+ R: K! }" F- ^, O4 W
  7.         __IO uint32_t HSEStatus = 0;6 H/ g- n8 A1 H0 L$ n
  8.         
      T- i; Q& u. S# }
  9.     RCC_DeInit();  ; v* e! w  i& @( |

  10. 7 M4 B6 M  P" x- T0 v( U2 L
  11.         if(RCC_PLLSource_HSI_Div2 != RCC_PLLSource){        //选择外部时钟5 _* n6 k1 k, t9 G3 J. D; v5 R% o
  12.                 RCC_HSEConfig(RCC_HSE_ON);                                    //打开外部时钟
    2 s" U  F1 ~& q( V4 ^) M
  13.                 if(RCC_WaitForHSEStartUp() == SUCCESS){7 z5 \  ?) c8 A' B9 J
  14.                         HSEStatus = 1;                        : b+ }- u0 r; w/ |2 f( a, i
  15.                 }) e4 L0 M5 d6 v  I- K* t3 u
  16.                 else{( a5 \! A0 x' `0 f; m
  17.                         RCC_PLLSource = RCC_PLLSource_HSI_Div2;        //自动选择内部时钟
    3 E1 y4 s5 C% M+ n0 m
  18.                         PLLMUL = RCC_CFGR_PLLMULL16;" A5 ~3 F; ^6 `  ?  L
  19.                         RCC_HSEConfig(RCC_HSE_OFF);        //关闭外部时钟4 ^0 e5 `2 M; d' r
  20.                         RCC_HSICmd(ENABLE);        
    - B* L8 w3 T/ @: n6 A1 x' U+ K! m
  21.                 }
    5 }3 |) J& o4 a4 W5 D; x% a
  22.         }& Q9 i& A8 D7 |0 [& ]# v6 V
  23.         else{        //内部时钟$ G/ }5 X3 z5 M2 b( R/ M, d2 k, y
  24.                
    4 ]2 M2 b8 ~! P% a
  25.         }
    , H7 c8 D  A0 \) `- Q) J( {
  26.         . O+ f+ u% K$ ?; L' {
  27.         RCC_HCLKConfig(RCC_SYSCLK_Div1);                                  //HCLK(AHB)时钟为系统时钟1分频                        % a0 W4 Z+ V  U& j. G
  28.         RCC_PCLK1Config(RCC_HCLK_Div2);                                    //PCLK(APB1)时钟为HCLK时钟2分频
    9 X, f! r- N, i6 {: v8 L, w8 q6 U
  29.         RCC_PCLK2Config(RCC_HCLK_Div1);                                    //PCLK(APB2)时钟为HCLK时钟1分频        
    6 K( |" g& G: ^" d, ?0 L

  30. 6 J; q/ g: ^. e- J  S
  31.         //0-24MHz时,取FLASH_Latency_0;
    " [% w$ R: x8 [9 j1 O
  32.         //24-48MHz,取FLASH_Latency_1;
    0 t/ W7 f' ~$ M0 k( h8 X8 `
  33.         //48-72MHz时,取FLASH_Latency_2。3 t: R: J* ]9 H, H" ~. t; y
  34.         FLASH_SetLatency(FLASH_Latency_2);5 s) J7 V6 |. A. I- |) `! z
  35.         FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); 8 C, c- }  P/ c8 E3 Q' ^& S: ]
  36. ' q. R! }5 i, z1 h' m9 q
  37.         //PLL时钟配置,时钟源 * PLLMUL" A/ M1 x2 D2 f# g% C( b' N: Z! N

  38. 6 @3 q  V8 n; q' q. r9 s1 [; _
  39.         RCC_PLLConfig(RCC_PLLSource, PLLMUL);                 
    # M, [- s! s! W: u% O
  40.         
    ' _/ v  E6 h. u% X4 S' O% ]! |
  41.          
    # ]2 A9 X, h: Z7 W
  42.         . e# f9 i/ G2 K, {' t/ ~0 W; T
  43.         RCC_PLLCmd(ENABLE);                                         //开启PLL时钟,并等待PLL时钟准备好
    3 A' S+ [6 ~0 i4 f3 y8 ^9 I
  44.         while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);8 L  q8 m* X6 f. f2 j
  45.         RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);                              //选择PLL时钟为系统时钟
    # O0 x8 P+ K" P2 X# L
  46. & i, v% {9 m/ O% n/ f& a! g( z, S! S( Q
  47.         while(RCC_GetSYSCLKSource() != 0x08);                              //Wait till PLL is used as system clock source, {: F: @+ W+ j. z7 [( i& ?
  48.         RCC_ClockSecuritySystemCmd(ENABLE);                                                        //打开时钟安全系统- K6 U' @" n  b* f
  49. }
复制代码
! M, E+ T4 t' C1 g% {
一般情况下单片机的时钟配置是单片机程序中的第一步,也是很重要的一步。这时候我们需要考虑以下几个问题。
, ]% x& ?2 L# m6 [* n: K6 t7 S9 q' D' b, n+ Y: w
1. 系统时钟的时钟源用哪个。, @' ]2 ^3 ?; z2 M$ V# v
6 @8 R$ z8 {/ C+ c: x9 i
2. 系统时钟频率要多少。
' ^5 h6 j! u' f( j& f9 E! E8 j4 Z% r. ?+ i6 E
3. 每个模块的时钟频率要多少。0 v- m; q% o# E

$ v# v" ?) m( A4. 如果外部时钟出了问题,这个时候时钟是怎么运行的。
3 o4 r  p, N% r/ F: {) y! @2 y, l/ x
下面就针对性的讲一讲STM32F103的时钟配置。
0 V" W* S9 y$ a/ Q! Z1 N% A- M, I知识点:
1 ]0 U* h+ k( L1. 系统复位后,HSI振荡器被选为系统时钟。当时钟源被直接或通过PLL间接作为系统时钟时,它将不能被停止。
& J/ }$ N$ H! E# I8 C/ L) @+ U6 S+ K. r) T+ D& R- j6 H5 u
2. STM32F103的三个可以作为系统时钟的时钟源,分别是HSI、HSE、PLL。而PLL的时钟源是HSI/2(内部RC振荡器二分频)、HSE。
7 L* a  j! d" n4 B) C, @
  z2 u3 R+ u) N1 @, a3.如果使用HSI,系统时钟我们能达到的最大频率是64MHz,如果使用HSE,系统时钟最大频率是72MHz。+ \( D) ?# I. J) B- {9 {
) h, ?" Q/ I  X0 [2 t# w1 G* Y  ]' `
4.APB时钟有低速PCLK1和高速PCLK2;PCLK1是从HCLK二分频得到的,最大36MHZ,根据上一条知识点如果是使用HSI,则最快是32MHz。
  H" K6 a) V4 e. d8 ^9 @) t8 S3 h
$ Y# q$ @6 n: {0 K5. PLL的设定需要在使能之前,一旦PLL使能后参数不可更改。& H$ N- i7 S1 T4 u3 X9 V
) B0 G* O$ P9 c+ D7 f. `* L5 e
6.附录是一些缩写的英文全称,也有一些补充的知识点。7 k" m0 ?, k: Z7 {3 D, R

, }' ]- A5 r5 ~5 d1 h  @* r  t, t# F& m8 ^
步骤:# k& {0 i! V+ O& M6 A
$ L& _' E/ N& W- [
第一步     初始化时钟
: l1 ]  j2 y& n/ d
( b; A$ Z' J" h3 m& v( K         不管现在SYSCLK的时钟源是哪个,我们要更换时钟源。先RCC_DeInit();
% n  C3 g- d" [9 [+ S) O! c! @8 H
$ z: ^  E9 E& J: M& j第二步              打开时钟& `' |, y1 f* i
1 p9 `# y! a% u3 g) r! |5 O3 C
         内部高速时钟HSI           RCC_HSICmd(ENABLE);& W/ U( ~; U% o2 z' z6 T6 D  _$ B

- g. f7 y% R6 I1 s2 @         外部高速时钟HSE          RCC_HSEConfig(RCC_HSE_ON);: B$ o; I* u4 u6 c8 J; n' u! |
  ]: N" H' o' `8 J
第三步              等待时钟晶振工作2 C  [$ x1 G* y# R( i: c: H& b" Y0 n+ \

4 r* |% z  d" _1 _' V& T         HSI            While(RCC_GetFlagStatus(RCC_FLAG_HSIRDY)==RESET);
& n/ R+ N7 J6 n, l! L! s, ^9 B4 z3 l& w# h0 Y- L# K! k  N# H+ G
         HSE           While(RCC_GetFlagStatus(RCC_FLAG_HSERDY)==RESET);' f* W8 N; [2 y  r

& G, W. |& R0 C/ x# u* w第四步              设置AHB时钟HCLK' F7 Z. A# `, G8 a# ]

8 @1 O7 Z' L0 D; ^7 M- u+ i                                                                 RCC_HCLKConfig(RCC_SYSCLK_Div1);
/ g4 n: A/ p, z( A" i3 \
8 N% Z5 O, H3 R* n$ J8 m% E+ k        分频系数自己设定,一般都是RCC_SYSCLK_Div1即不分频。
3 X& q- s# ?9 {( p, m' ?% x# y; M) h0 X7 J5 v8 o
第五步              设置低速APB时钟  T, W+ P! s3 j" D. U
& S! A3 x# G$ b. Z/ I+ _
                                                                 RCC_PCLK1Config(RCC_HCLK_Div2);6 O7 ^+ T8 b+ y# f
& f% z; d2 H! h  i( B
第六步              设置高速APB时钟- l3 `( R& i8 `4 e" p* Y
7 M; P7 ]  C- O
                                                                 RCC_PCLK2Config(RCC_HCLK_Div1);0 U4 ~2 Z' X4 e0 Z
" R1 }% Y, `+ `: Q+ ^" d5 o
第七步              设置Flash预缓冲( C# X5 O# ^2 Q- E. K2 l7 C. h- a

, O' E% N  {/ h& h                                                                 FLASH_SetLatency(FLASH_Latency_2);
1 m$ j8 B5 R" [5 ~1 ?* f+ H# q  m
! V/ q8 _3 |1 I4 A( q                                              FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);          // 使能flash预缓冲- u4 H  k, |  B% K, {
. ?7 a+ R0 w' P% m# V; W
       Flash的操作也没有总线时钟快,所以需要总线在操作flash时稍作等待。推荐根据HCLK设置。/ {, q- }+ c) d' ^/ w
( ~6 A2 \$ Y! |9 w3 [' l; c
0-24MHz时,取FLASH_Latency_0;24-48MHz,取FLASH_Latency_1;48-72MHz时,取FLASH_Latency_2。
7 U& ^+ G# A% m# x
3 e  X" F  ]9 Q; t  U! ^- b2 B) g  r
第八步              设置PLL                     如果不使用PLL,请略过此步骤$ C: ^1 s* n6 g

0 q5 A8 W4 G# @  q! v8 S         HSI                                                  RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_16 );& e6 _6 F5 j1 U6 ~6 ?+ t/ o2 n/ H$ c3 b
2 D1 z+ H0 l4 T  O  n
         HSE                                                 RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9 );
, r7 `/ k4 U+ K. m0 p- G, h0 T4 F1 Z) u9 k5 a/ Y0 d
第九步              打开PLL                     如果不使用PLL,请略过此步骤0 e3 ~4 ?# g& j; v" _! Y

0 H8 I- N+ n7 c. X; r8 g- \6 ~! v* i                                                                 RCC_PLLCmd(ENABLE);
8 h/ m5 m7 {$ o! ~) R5 {; p: I/ B3 R4 s- [  ^7 y- \
第十步              等待PLL工作          如果不使用PLL,请略过此步骤. }0 }2 _/ x& }9 i. D! G
2 D) s& O6 N5 _9 d
                                                                 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)== RESET);( j0 R' L1 Q1 W9 Z

" y( E( m$ l  K) j1 U% D5 \第十一步              设置系统时钟
) Y9 }  u& ~4 h# o/ s  j9 ?0 j# k+ E
         HSI                                                  RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);5 C/ @; p% c+ P' b
- ]! m0 M: h( J+ c6 j
         HSE                                                 RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);& \. X6 V0 I9 S0 ^5 T( V3 x, R( w

4 ~7 A$ D: h4 B, g4 g         PLL                                                  RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);" O) b$ }; s4 p
7 J7 o3 c. ~4 j9 ^
第十二步         判断是否是设置的时钟( r/ n; F9 |  ?* k

& d0 c  f1 a& F) E% L         HSI                                                  while(RCC_GetSYSCLKSource()!= 0x00);
, W2 G: o* G. A! C% `. Y7 j7 r) x! W# T6 h: o
         HSE                                                 while(RCC_GetSYSCLKSource()!= 0x04);" S* x8 d% K& d

& F( A5 I8 f  E3 \8 \) ~         PLL                                                  while(RCC_GetSYSCLKSource()!= 0x08);
3 B$ Q7 n6 Y& i) T, V+ p3 p5 ]
$ S! Y  _) F! q3 s5 O! b- f6 f附录:一些缩写的英文全称及中文翻译,帮助理解记忆。
$ y9 J, y. w3 c# P2 h/ C0 Y* F
2 G( \8 [' ~. `% A1 w5 J) qIWDG       IndependentWatchdog                                   独立看门狗
6 Q' V) D6 r) U( L+ r5 H; [( R# [
RTC           RealTime Clock                                                      实时时钟) O+ z: K  s' l" ^1 K
3 u9 s- ^* {5 s
                   时钟源可以是LSI,或者LSE,再或者HSE的128分频。
- h; q0 W8 {8 Z8 x$ X
7 z- I& U2 d2 n) a4 H4 A) DLSI             LowSpeed Internal                                                       内部低速时钟
' ?/ k, _8 F" U4 B0 K1 q3 j5 J/ s# g3 N, b) _* a4 E3 n( N
                   RC振荡器,频率为40kHz。供IWDG使用,还能作为RTC的时钟源。" C4 K! j+ i) l" |1 }9 ?
. F/ F, }2 b3 v6 n. g& }, l
HSI            HighSpeed Internal                                             内部高速时钟
8 l3 i5 W7 _: Z4 j+ v2 d/ ?* Q
, b$ o" q. [# I! F. O. F                   RC振荡器,频率为8MHz。
1 W0 F! x0 g  m) t& K; D
; F& \% g% k; l1 Z, w# Q9 g& NHSE           HighSpeed External                                             外部高速时钟9 H' H+ K; {! \' [- Q% a

5 x' J) @: p) V: Z  H' J                   可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。
, ~% n* Z4 X7 [* E% G% ^# D7 J0 V' W2 A% N; i  P% F
PLL          PhaseLockedLoop                                                   锁相环倍频输出
* r& J* D5 N0 q- x7 r1 b( x$ O* s, F. d/ E
                   其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,
; J' A& i& l) g2 J0 ^  {2 w/ @+ }# `) V( t4 X5 k) Q/ {
SYSCLK     SystemColock                                                                 系统时钟( s' [0 u, Y8 |' @. z( S$ ~$ a2 i) |
2 x+ a8 @9 o1 J: w3 `9 Y
& G& S% T5 F6 q: S1 R+ s

8 b7 D- E& {) p: f! N0 YAHB          AdvancedHigh performance Bus                   高级高性能总线
" p$ G, A' k" b9 ]2 q
# l: _' P. \: t. c+ [                   AHB主要用于高性能模块(如CPU、DMA和DSP等)之间的连接。
8 [* L2 T5 n1 ]' B% v  b& i, h! F9 b+ I' m4 T2 c3 r1 B

+ e5 C9 S( n) A+ x# _/ j6 l& T, R* t/ T) N: w7 m( J3 f
APB          Advanced PeripheralBus                                  高级外围设备总线
* K8 V( a' a6 j2 L: |+ B( c' z" R4 t7 M, K5 S1 I# @3 G! c/ I
                   APB主要用于外设模块(如ADC、USB、SPI、UART等)与AHB之间的连接。4 e+ E1 j# L4 K% ~/ A5 [

& {! U) E1 U* X- DHCLK         Advanced High performance Bus Clock                 高级高性能总线时钟
9 [2 m& k' u$ r" o  r* `9 g% J" T- X# h3 m6 T; C
                   就是SYSCLK经过AHBPrescaler(预分频器)后得到的AHB的时钟。9 Y0 ~( f2 R) d: T5 Z

4 H5 g/ U& t: I0 WPCLK         PeripheralBus Clock                                            外围设备总线时钟                  
% @: w$ L2 [! }$ p# O) P$ k
$ w5 I. H2 T) w, T                   PCLK有两个,一个是低速的PCLK1,另一个是高速的PCLK2。
: ~! F, c6 E* {) h  Y, M$ W# G" |8 g7 u+ H
                   PCLK1是经过APB1Prescaler后得到的APB1时钟。8 M/ u- ]- g+ c4 M. _! a! n

8 L. }. A# V2 m: i8 _" s* g4 _PCLK2是经过APB2 Prescaler后得到的APB2时钟。, ~3 O' E% n5 T5 c4 Y

; i8 H1 s7 D2 O6 f& B8 @; h' E  wFCLK                   FreeRuning Clock                                                  自由运行时钟
, J( l' _# O5 ]) F; ]* s: {9 C" a# _7 O* r9 P, }0 e
为供给CPU内核的时钟信号,CPU的主频就是指这个信号;1/FCLK就是CPU时钟周期。
1 h! K5 d% k+ W3 U
0 p- o- |  H# [( v2 g7 B为什么叫自由运行时钟呢?下面是别人家的讲解。
: a4 h7 X0 ?7 ]/ }0 B, Q" v* x  }! n" t- h1 _
ARMJISHU注:FCLK 为处理器的自由振荡的处理器时钟,用来采样中断和为调试模块计时。在处理器休眠时,通过FCLK 保证可以采样到中断和跟踪休眠事件。 Cortex-M3内核的“自由运行时钟(free running clock)”FCLK。“自由”表现在它不来自系统时钟HCLK,因此在系统时钟停止时FCLK也继续运行。FCLK和HCLK 互相同步。FCLK 是一个自由振荡的HCLK。FCLK 和HCLK 应该互相平衡,保证进入Cortex-M3 时的延迟相同
. S: H  F5 v# @! n' v; O' M
: F0 }% r4 x" R% N0 [$ y) D# Z/ X, M+ ~
" i; l) p* o& v7 L1 @; l
赞 收藏 评论0 发布时间:2022-3-16 10:57

举报

0个回答

所属标签

相似技术帖

官网相关资源

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