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

STM32F103时钟系统讲解

[复制链接]
攻城狮Melo 发布时间:2022-11-8 23:05
一、STM32F103时钟树
$ Q) X: n3 N8 s+ Q" Z  ^! t  首先先放一张STM32参考手册中的一张时钟树,对照着来讲,如图所示:9 g% y8 b# l: B, x$ D

, V3 b4 N  [+ \2 r0 \$ K; q 77f85107db1a437cb9dfeead7af43789.png # _5 u- @, d) V

, v7 r  R+ L# U# D3 }. a  首先对图里出现的几个名词做个介绍:
7 f4 P- r  ^$ i8 r6 M0 x VS}CN8LOJ96ESYR%D_$OE6R.png
" O0 s: i. p/ G3 ?  C$ y
( K' R& Q, h- I8 W% b# Y/ s# U& `4 \" b5 ~* F+ F/ J2 J
  为了更加清晰直观,再放上一张STM32CUBEMX里配置时钟系统的图:6 O! |+ I' ]- }8 e$ Q6 @1 Z  B

' y! k8 m  Q% D# G d2e146e2ae1e4619809d6f78faa0ea59.png
8 b: g4 |5 |/ T+ F" j( d# U! o  X( t7 q
  首先先明确一点我们的STM32有HSE、HSI、LSE、LSI、PLL五个时钟源,接下来会对这五个时钟源进行介绍。
8 |; }' f( d; D' |- T$ e& W+ y( k1 y6 `2 i. L9 o8 ~
1.1 HSE、HSI、PLL、SYSCLK
: b  E/ C( S( R' g
  我们想要配置的时钟是SYSCLK即系统时钟,我们一般说的STM32F103时钟72M就是指这个SYSCLK系统时钟,从图里可以看到,配置系统时钟的时钟来源主要有三个:
2 h& t2 X% g1 O9 T
: c- K/ ]& y! l2 f: y& G8 B. I( T4 W 8b3d31099fcf45bb99e8408b656d3a0b.png
5 @. X4 d; Q0 N& h- N2 ]) X/ L9 o, g0 Q. b- x2 X2 v
  分别是HSI、HSE、PLLCLK,我们配置系统时钟的来源可以是外部高速时钟、内部高速时钟和锁相环PLL出来的时钟信号,我们都知道在MCU没有超过最高时钟频率运行之前,时钟频率越高,系统运行更加稳定,故我们配置时钟时一般都是希望配置的时钟频率接近上限。
0 C/ U7 A- W8 w! s* h7 c4 n  在STM32F103芯片里HSI给定了是内部8M的高速时钟,HSE可以是从4~16M之间自己选择焊接任意频率的晶振,而PLL锁相环是可以将时钟频率倍频提高可以实现稳定且高频的时钟信号。我们先来看一下PLL锁相环的时钟线:
# ]3 |( z3 S5 y3 l6 o
0 E- f1 h, M. R6 {+ B7 k0 c 2ecd16f905bc4a81891b091239d1bf3e.png 1 \+ s* [" b/ L- [% t

( w; w  T/ l! U, R  PLL锁相环的输入可以是经过二分频的HSI也就是4M的内部时钟提供的信号,还有外部高速时钟HSE可以不分频或者二分频的信号,一般来说我们都会采用外部的时钟信号更加的稳定和准确,这里我们单片机外部焊接的是8M的晶振故我们选择PLL输入来源是HSE,在PLL内是经过*PLLMul(*9)来实现达到72M的频率,最后输出给到SYSCLK。0 K: s! d' u( J3 ^( ?/ T
; |3 p5 h( j% |4 V' N  H4 A2 o4 R$ x
1.2 LSE、LSI、RTC
3 K+ h1 d% w7 ~" \- h4 |  S1 ?  讲到这里HSE、HSI、PLL、SYSCLK相信大家都有了认识,接下来还有两个LSI和LSE有什么作用呢,我们看到STM32参考手册里有这样一段话:! ?& k8 X" ?0 V+ R) o% Y1 E/ \. w

- P* t- \, d  B0 b' ]+ K 0e1ea34bf28b4d6ba0c13067d53ddac0.png
6 O0 C6 X, X+ P+ E: `# M9 I1 X& L8 @/ }) e" X0 b6 R. X
  我们的芯片内部低速时钟LSI是40khz的,用来驱动看门狗或者是RTC时钟的,外部的低速时钟是32.768khz可以用来驱动RTC,很遗憾我没有做过关于RTC的实验,故对实时时钟的解释不是很充分,没有特殊要求一般不会去用到,如图所示:+ v) |8 c6 F( ^+ E2 S1 ^/ K0 v1 d

, k; E" @$ q1 i0 C 822a6f9f206d4ef3aa890c479f35dbb0.png ) W9 N# m+ L: j0 C- |! D* `

8 O! R5 t5 S1 g1.3 重要提示
3 t7 G8 k0 l5 H4 s' f- M1 R6 ~  上面介绍了五个时钟源,我们在不使用时,任一个时钟源都可被独立地启动或关闭,由此优化系统功耗,比如说我只用了一个HSE和PLL来配置SYSCLK,那么其他的时钟源可以不需要开启,以此降低功耗。$ N6 P. ~  R0 `1 P4 Q

: _' U( E9 K/ ]2 c1.4 HCLK、PCLK1、PCLK2
6 n) H" w' X- |  配置完SYSCLK算是完成了时钟配置的一半,我们接着看时钟图后面,如图所示:
$ Z: K  o; d& ]3 \8 I' ]' A: l2 G% {$ d+ A8 T- H  e! x6 K, d+ R
5651f43bde2e492c90dfb9f23a0d395d.png 3 e% @+ y2 V4 j% P; V6 z
' p/ `8 `4 m: B# h4 W. o; R  A
  SYSCLK系统时钟出来后可以看到会经过一个AHB预分频器,将分频后的信号给至HCLK高速外设时钟,STM32规定最大的时钟信号是72MHz,和我们配置的SYSCLK一致,一般都是将SYSCLK配置为最高的HCLK时钟频率之后预分频器分频系数给1,将SYSCLK和HCLK时钟信号频率配置最高,以此达到系统高稳定性高性能状态,HCLK出来的时钟信号会给至AHB总线、核心存储器、DMA:( w( C: M# V) K" h1 m
# d( {( ]: _: D$ R% J( P. s
f7c67056acce4ae6b3381cb8f768a4fe.png
1 x1 m/ ~" J0 {6 t8 q" j+ e- U
) ~8 Z% \# m2 g% }  STM32还设置了两条外设时钟线,一条是PCLK1低速时钟,另一条是PCLK2高速时钟,PCLK1经过AHB1预分频器分频最高可达36M,PCLK2经过AHB2预分频器分频最高可达72M,如图所示:
7 `! `7 N) r) V% u( y, q6 x- q
2a34abc27940462e994b36a25b83c57b.png
6 r- @+ W  P& O* |1 f# N* b
% m1 h( i7 F7 }  在外设中存在着比较特殊的比如定时器,如上图所示,在APB1/2分频完成后有对搭载的定时器TIMER进行了分频那么怎么确定应该是多少呢,可以在STM32参考手册中找到这样一段:
( g: A* S( H% f
6 g! z  k& A" f6 a0 Y6 c/ ] e697b83e5c4d43a198d9c0168df8569f.png   R* L! ?4 ^9 @0 J9 P

1 |2 q" @6 V+ H+ C, \3 B  为什么需要这么多外设的时钟呢,我们都知道在操作STM32外设之前都需要打开对应的外设时钟,比如我要操作GPIOA01输出高电平,我需要先打开GPIOA的外设时钟,才能对引脚进行操作,如下图所示是STM32F103各个外设时钟搭载的外设:
8 {3 [1 [- c( }; e8 x& N. `  AHB搭载了DMA1/2、SRAM、核心存储器等都在HCLK提供的时钟频率下运行,比如想要用DMA1就需要通过打开AHB下的DMA1时钟,时钟频率就是HCLK,才能使用DMA1。+ x* ^9 F$ Z2 z  T) v
# p2 M1 H% g3 {! x" Y8 }% T
194daa2843a54fd782b2c90e06401903.png
! ?) e5 q; ]' j- i4 O2 O8 L- F$ t3 V! w7 V: b4 x2 F1 \
  APB2搭载了例如GPIOA~G、ADC等, A0 c3 G+ b( V7 _& {& n
$ M( l2 _1 k. V) Y8 z9 ?/ X4 w9 M
6e178c0262b94cb8a93dd5d896f5ae93.png
- D/ S- S  E  _; V
( m$ I; Y2 S$ @9 n: q- k+ m) q4 J  APB1搭载了通用定时器、USART、CAN等外设2 j* M& U: u: ^0 r( L/ `3 w

6 Z) ^7 n  z6 h5 w 61bb9fb180c74d2dbf0079bc8061e673.png 9 v9 B" Q) N9 @* }
8 j- X. h+ Z* J9 d6 N
1.5 时钟树小结7 F7 G( a" Z! H4 u: w* b6 e
  一条较为完整的时钟配置路线大致为:HSE–PLL–SYSCLK–AHB–HCLK–AHB1–PCLK1(/–AHB2–PCLK2),综上就是STM32配置时钟树的大部分内容,相信大家对时钟树的理解进一步加深,接下来我们讲怎么在标准库中配置我们的时钟系统。) r+ p2 i9 ?, T" t

* ^1 C+ \) X8 H8 d7 f# L  d, J二、程序配置(以之前新建的工程为例)7 r! S7 k5 x' q9 f; [  l. C
  第一步打开我们的工程文件定位到startup文件夹,双击打开我们的启动文件,如图所示:2 B! Z7 c: \' d% J9 F

8 w# y+ S8 p0 [; v; h# K c078b8b58699408f957e08da30672f4a.png 8 _- e! w' K* {* l; g% S" C, s3 ~

" {1 W: E8 w  x3 y! J  第二步我们知道STM32程序都是在启动文件里开始执行的,所以我们下拉代码找到程序运行的入口SystemInit,选中SystemInit鼠标右键单击Go To Definition…或者选中后按下快捷键F12进行跳转,如图所示:
7 G. {( y( `( i2 t) ^# M. l4 Y3 ^& w- V; F0 f
35d0948319044dfd83a92571bc8949d0.png , d. G; y  ?! s6 F3 v2 Q% V

( d# m* ~# G7 E, B/ ^1 Z) d  第三步 SystemInit函数刚开始是初始化了很多与时钟相关的寄存器,将RCC时钟配置重置为默认的重置状态,往下看会找到一个SetSysClock()的函数,再次跳转,找到函数主体:% t3 @& [- E: V9 N" N1 k0 b, U
! K! _# k5 Z. b
0c39ddb35354468e918073257ab7643f.png * }( J' p. e0 O! Z! `
- q5 m+ ^  [0 Q8 r% P
  第四步跳转后可以看到这里通过判断标识符的方式将会执行SetSysClockTo72()函数,我们设置了72M的系统时钟,可以点击宏定义标识符查看,根据需要可以选择不同的时钟频率,如下两图:
; z2 c5 r% [! v6 E( e% d5 F" j" k  p' e- \
13211d478bca4f5387d092e12099f3f1.png
8 i  n( W. N5 ~! S, J0 i9 V
4 h4 z3 \# _4 y 47d635e25e6145808327d5b94f289cb0.png ; J' H5 R6 f# l& P

* e) p$ \. q/ V; C$ u' @  第五步再次点击跳转SetSysClockTo72()函数,可以看到,我们进入了真正的配置系统时钟的地方,该函数起到设置“系统时钟频率”为72MHz,并配置“HCLK”、“PCLK2”和PCLK1预分压器的作用。整个系统时钟配置的过程是先启动外部晶振等待稳定然后设置好AHB,APB1,APB2,PLL相关的系数再启动PLL维持稳定后完成时钟配置,可以通过官方提供的注释看到,比较关键的一段如图:
2 r1 ^" p( F; e4 w
* O7 B/ a/ H8 }7 u bbcf4f2212d94df5be9998fbccea0178.png
$ _% E7 H7 a+ w) c+ x! f  s0 ?; {" }
  可以看到,HCLK配置为分频系数为1和SYSCLK频率相等,PCLK2分频系数也是1和HCLK频率相等,PCLK1分频系数为2是HCLK频率的二分频,但是注释却打了相等可能是注释打错了。
- B) `0 Q+ p( @4 r6 s* Z8 T; i2 D  O7 d' `
35e64dd4d70c4b32911514a3b92b7704.png & U# ?4 z6 Q# m* y6 ~$ I+ D( k; t4 ?; q% E
( J6 v' q5 n8 C# c
  这里是PLL锁相环的配置,需要留意的是RCC_CFGR_PLLMULL9这个参数,最后HSE出来的信号会乘上9提供给我们的SYSCLK信号。
# e/ L7 B% C! c) e  第六步到这里为止所有的分频系数参数都设置完毕,最后要等待PLL提供稳定的时钟信号,整个系统完成时钟配置,如图所示:
2 B  |: W: k7 w1 K3 }
: C2 `! ~, K+ h$ ~ 4ea3c96935b04b7c8b246306f4a1172d.png . z& D- I9 _/ H7 {! b

, M8 w( X- o3 C! }8 g. v$ o  注:那我们通过程序查询比如HCLK的时钟,程序怎么知道HSE是多少呢,我们可以看到在stm32f10x.h里有一个HSE_VALUE的参数,这个参数定义的是我们使用的外部晶振的频率,这是8M,如图所示:. a) }! _$ ~' r
1 B1 A9 f% D6 K8 ?" q' {5 J) @
b57ce450ce334d52980f93988386d3b9.png
, Z4 L+ d8 w/ A% x  B. ^3 `8 D& U4 ?  y  t
三、小结
) h( n- L6 E6 I: B( i  这一讲我们认识并强化了对系统时钟的概念和理解,对程序的配置上有了进一步的认识,大家可以在自己研读一下设置时钟的程序,这里程序讲的比较省略了关注点在时钟配置上了,下一讲会教大家如何运用keil5的DEBUG功能查询我们设置好的时钟频率究竟对不对。/ n4 f% E6 p5 L+ M7 c
————————————————
* [# f6 {- x# V3 U5 E0 \" [版权声明:水水爱污污
' L  F% ]5 x: M& Z0 Z
. }& B* h7 d: I. R9 y9 z( C+ h( {/ {1 j$ w& T7 ^. p
赞 收藏 1 评论0 发布时间:2022-11-8 23:05

举报

0个回答

所属标签

相似技术帖

官网相关资源

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