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

【经验分享】STM32F10x从零开始配置时钟

[复制链接]
STMCU小助手 发布时间:2021-11-30 22:16
实际上,对于STM32F10x系列的芯片,如果使用库函数方式开发,芯片的时钟初始化函数已经写好,并且在启动文件(例如startup_stm32f10x_hd.s)中被自动调用,在进入main函数之前,系统以及外设时钟均配置完成,main程序中不需要对时钟再进行任何配置,直接编写应用程序即可。但是作为一个底层驱动玩家必须要打破砂锅问到底,看看STM32F10x系列芯片的时钟系统到底是怎么样的以及如何配置时钟,下文将着重分析STM32F10x的时钟系统以及用寄存器方式从零开始一步一步配置时钟。
1 c8 t, i. E6 R
/ d9 M3 g0 t- H  u6 R+ M% @- z一、开发环境
5 x' V) y0 e5 j1 ?% {& ]MDK版本:V5.28
! ?' M; ~3 u- h) o单片机:STM32F103RCT6
6 Q/ `- D5 G2 I$ S( h1 Q; R二、时钟树剖析
% [- ]4 z2 B# i" P9 s
& r! ?3 d. @6 J( @& T! f
5}7)N_$J[]~[E6]{CR@H)[Q.png

. j' N5 \! H( Z- U
! Z6 ]% k) w8 z( l! c  N0 a上图就是STM32F10x的时钟树,看着十分复杂,或许有人会问,为什么STM32要把时钟设计的这么复杂?这是因为STM32的外设很多,而且不同的外设需要的时钟是不一样的,例如USB时钟一般需要48MHz,RTC时钟一般是32.768K,APB2总线上的外设最大不超过72MHz,APB1总线外设最大不超过36MHz,如何同时满足这些时钟要求呢?显然如果只设计一种时钟是不可以的,于是就有了上图中复杂的时钟系统。下面我们就来分析下上图的时钟系统。9 H! k8 `) R$ l- t" i
! X; ~1 U, h% W3 m2 B9 L
首先可以把上图的时钟树划分为以下几个部分:
/ i% D  @" P, C
6 h4 z" |8 A$ J( Q$ C
6KXC8$)[K}1`$~AGTTMA(G9.png
4 E2 D; p7 K0 q7 ]- k% I

0 \* E- x7 I" q" X
_T]8Z)V%2VIEX0BYS2831MD.png

6 s; Q4 V, x, ]' N  Z' w: L7 C8 B* q7 ?9 U  G, N; i, c% W* k7 C
基础时钟介绍:* o# _; ]  F, f& z0 Y- ]
/ g9 w& F6 c0 L, Y; `
$SEZ~2)7W9YS)29YIGNQ`AE.png

" O+ R+ x% i# V3 M8 ~4 R7 p2 k8 @2 i
/ x! S4 h, ?8 q# y/ K' }基础时钟并不是官方提出的概念,是我个人的习惯叫法,它主要指的是HSE、LSE、HSI、LSI这四种时钟源,其主要作用如上图所示。
: I, c* Y8 q# i: ^2 W% G! J. o3 @3 b
系统时钟的产生:
3 ?$ b; t2 P9 Y7 R7 T) M3 `8 Q2 f  ?  t! g5 Z! Y* B0 r/ |; L
ZXIP7BFKM02TZ%`[2YG_XQN.png

) Z; b; o" p! u; P1 }
+ H* e% {% m6 P9 p% j1 y0 C! W& V系统时钟的产生有三种方式:1>HSI内部高速时钟,一般为8MHz。 2>HSE外部高速时钟,一般为8MHz晶振。 3>PLL电路,输出频率可任意配置。其中HSI和HSE都属于基础时钟,如果使用PLL时钟作为系统时钟,PLL电路的基准输入必须是HSE或者HSI。
0 k7 f7 r' @: l6 p) e! c5 l如果直接使用基础时钟作为系统时钟,那么系统时钟最大频率≤HSE/HSI 如果使用PLL输出时钟作为系统时钟,那么系统时钟最大频率≤72MHz. s  T% z) `0 w& t$ B8 ^

  Z* G1 q% Q% C下面就以定时器为例说明上述各个时钟之间的供需关系:! b/ |) F$ C- f! p- N  S% x) g5 k7 z

$ w3 L, s1 ?6 c' P7 ^8 V如果需要使用定时器,那么首先需要开启定时器的时钟,而定时器属于外设,因此需要系统时钟提供时钟给这个外设,对于系统时钟,有两种方式提供,一种是由基础时钟(内部或外部基础时钟源)直接提供,缺点是无法产生更高的频率,时钟源是多高的频率,系统时钟最大不会超过这个频率;第二种是由PLL电路提供,优点是能够产生各种高频稳定的时钟频率,但是也需要基础时钟提供基准信号,且一般情况下STM32F10x系列PLL输出最大不超过72MHz。
& l" j# A7 M, Y* n& T# b5 F' A一般来说除RTC外所有的外设时钟(TIM、GPIO、DMA、USART、USB等等)必须由系统时钟提供,但某些特殊外设需要另当别论(以太网、I2S设备等)2 c& Z- x% C% C# e
# x) m, l. q# L8 O, n6 y' j
在STM32时钟树中,还有很多的分频器和倍频器,通过这些分频和倍频器就能产生各种需要的频率,但是只有PLL电路才可以倍频,即产生高于输入频率的频率,例如将8MHz的HSE作为PLL基准输入,最高可以9倍频,产生72MHz的输出频率提供给系统时钟;其余的电路只能进行分频,如TIM、USART等这些外设时钟都是通过系统时钟分频而来,所以它们的最大频率不会超过系统主时钟。
3 K9 y2 u: E4 D5 ]$ i5 R" i  x& Q$ Q! K$ ^
三、时钟配置流程
8 g) i' X5 J9 V$ y" WSTM32F10x时钟的配置有很多种方式,如果HSE存在,那么可以使用HSE作为PLL输入,也可以不使用,还可以将HSE 128分频作为RTC时钟;当HSE不存在时,可以直接把HSI作为系统主时钟(8MHz),也可以将HSI作为PLL的输入,但此时PLL的最大输出为64MHz。LSE存在时,可以将LSE作为RTC时钟,也可以将LSI作为RTC时钟,看门狗的时钟只能是LSI(40KHz左右)。. }  X. [, F" m1 v' e
下面是STM32F10x系统主时钟及总线时钟配置流程:5 @: b! a1 F$ r" C3 F; v6 {" N

+ Y; k* d% \. l$ u: }6 c% @
TKY9]30$(OE40S(7([JIRBE.png
3 I* f# j: ^& N' D, s

/ p7 q, ]; r2 Y2 ]4 o; N7 N1.任意时钟倍频或者分频系数必须在该时钟未使能之前修改,例如PLL倍频系数,当PLL时钟使能后,该倍频系数数被锁定,无法修改,必须先失能PLL,再修改参数,其他时钟亦是如此。  ~! M' v: c% E+ X6 |5 _- d

* b' U9 a$ I+ Z2.PLL时钟、RTC时钟、系统时钟源切换时,只有当目标时钟就绪时才会切换,否则无法切换。一旦某个时钟源被确定,除非复位,该时钟源不会被停止
) g0 b3 q7 C; t% J' l6 b# l. x
1 ]5 A( W# ^& g6 u: ~0 s9 }现根据上述流程,一步一步的进行时钟配置:
% ^7 R* S$ H& V5 J' h- o# R尽管时钟树如此复杂,但实际上也就需要配置以下两个寄存器即可!
2 n( M) y0 C& y4 |) Z( |
: D1 Y: F1 V/ i9 R; n+ T$ b
9QOT@@1GNOR)TQDH9DSC{_3.png

* v' c: }$ S. E) q1 k$ s
3 Z( E, t9 f: M, a; C$ r/ U' f* s; @- q4 u. H! i
)F$VH~58H8C{`NFQB_N_E`S.png
6 u% H4 _2 u# ]9 H, a! Q# ?. q7 j

) |) A- U2 g' s' {$ H# KHSE配置(如HSE不存在则时钟错误)/ ]) B- q. M9 g! B
  1. RCC->CR |= (1<<16);//使能HSE9 D/ X* x/ b8 s& r- G
  2. while((RCC->CR & (1 << 17))==0);//等待HSE就绪, t9 @, [# M7 @; ]0 j. p* w( ^
  3. RCC->CR |= (1<<19);//如果外部 8-24MHz振荡器就绪,时钟监测器开启。( G4 C  R1 O& N- |
  4. 1 h. ^8 D& b0 E8 j$ t8 h6 q
  5. //下面是HSI配置 若有需要可以加上
    3 L" @8 [2 I* s! r
  6. RCC->CR |= (0x01);//使能HSI
    0 d1 t; J+ X9 H# e$ c" @
  7. while((RCC->CR & 0x02)==0);//等待HSI就绪
复制代码

. S) V! ^: G0 E  ^+ N7 n- D: \FLASH访问配置3 R  D; O8 B- }2 P
  1. FLASH->ACR | = 0x10;//FLASH启用预取缓冲区  f$ {) O4 i) T
  2. FLASH->ACR & = 0x03;//清0低2位
    4 Z/ o# A6 M- r4 P& c4 M
  3. FLASH->ACR |=0x02;//等待2个周期
复制代码
/ Z/ m0 ^5 h/ q' v+ N& \) ^
AHB、APB时钟分频系数配置
. n: K. x$ h( D" v# c1 f8 o" X
  1. RCC->CFGR = ((0 & 0xf) << 4)|(RCC->CFGR & ~(0xf << 4));//AHB不分频 72M
    $ b, D' B* G4 E# m2 |" ^% G  ~- q5 |
  2. RCC->CFGR = ((4 & 0x7) << 8)|(RCC->CFGR & ~(0x7 << 8));//APB1 二分频 36M 6 k/ Q7 z& A# H6 P" F9 s4 y- x
  3. RCC->CFGR = ((0 & 0x7) << 11)|(RCC->CFGR & ~(0x7 << 11));//APB2 不分频  72M
复制代码

3 V5 S' m8 J9 l+ ?( _1 ~' dPLL配置
3 s% j. G! l% b" R  k9 [
  1. RCC->CFGR = ((7 & 0xf) << 18)|(RCC->CFGR & ~(0xf << 18));//PLL输出9倍频  8M*9=72M: Q# R4 U! s8 o) M; q5 Q- }1 ~* D
  2. RCC->CFGR = ((1 & 0x01) << 16)|(RCC->CFGR & ~(0x01 << 16));//PLL时钟源选择HSE
    ! ]0 V, o9 z  V* v
  3. RCC->CFGR = ((0 & 0x01) << 17)|(RCC->CFGR & ~(0x01 << 17));//HSE不分频接入PLL/ q: I8 ~$ X0 d: C& k! f
  4. RCC->CR |= (1<<24);//使能PLL
    7 d) j  V1 i+ H# M7 k4 |+ L2 D
  5. while((RCC->CR & (1 << 25))==0);//等待PLL就绪
复制代码

/ _; z6 z7 F; a" r: P系统时钟配置. B, N- M3 N- `3 M" Y. H. L! @
  1. RCC->CFGR = (0x02 & 0x03)|(RCC->CFGR & ~(0x03));//系统时钟源选择PLL
    ; E- F8 d2 H: |, I) L: X- O
  2. while((RCC->CFGR & 0x0c)!=0x08);//等待PLL作为系统时钟源就绪
复制代码
. {$ z& |$ D% r+ ]' X! q! M8 l
这样系统时钟就配置完成了,如果HSE接的是8MHz晶振,那么SYSCLK=AHB=APB2=72MHz,APB1=36MHz 。这里并没有开启RTC、USB等时钟,大家可以根据需要自行开启。
% V; S+ o' o8 h+ v# Z对系统时钟的初始化,在STM32F10x的库函数system_stm32f10x.c文件中:SystemInit函数也有类似的实现方法,大家也可以参考下。' [; L* _# M* `4 L. Q0 u
8 B3 G! }! m. o6 D0 u/ z
四、备注
" ]. m% @& k+ U6 r系统复位后,HSI 振荡器被选为系统时钟。
& l; K1 e1 M/ S  l7 `' Y2 C3 j7 }. ?. ?
时钟安全系统可以通过软件被激活。一旦其被激活,时钟监测器将在 HSE 振荡器启动延迟后被使能,并在 HSE 时钟关闭后关闭。如果 HSE 时钟发生故障,此振荡器自动地被关闭,时钟失效事件将被送到高级定时器 TIM1 的断路输入端,并产生时钟安全中断 CSSI,允许软件完成营救操作。此 CSSI 中断被连接到 Cortex-M3 NMI 的中断。7 ^% \) a. `: M; t* K& Z, C' R

4 b- w- q: M1 \+ H如果独立看门狗已经由硬件选项或软件启动,LSI 振荡器将被强制在打开状态,并且不能被关闭。在 LSI 振荡器稳定后,时钟供应给 IWDG。
( K- F- a& y# G- W1 T% |
) F5 {* A/ I$ C$ bFLASH预取缓冲器:  H2 i# W, S: ~( N( O

7 U* k& N$ H3 A5 G. t复位后预取缓冲器处于开启状态) n0 d: G! v7 R& F

7 w- h$ L( k- K% t. m* P只有当SYSCLK低于24MHz时才能转换预取缓冲器的开启/关闭状态。通常在系统的初始化程序中开启或关闭预取缓冲器,此时微控制器运行于内部的8MHz阻容振荡器(HSI)。8 ~  a9 O& v% p% o. Z
$ C" K7 t  h+ j
注意:当 AHB 时钟的预分频系数不为 ’1’ 时,必须打开预取缓冲器 (FLASH_ACR[4]=1) 。如果在系统中没有高频率的时钟,即HCLK频率较低时,闪存的访问只需半个HCLK周期(半周期的闪存访问只能在时钟频率低于8MHz时进行,使用HSI或HSE并且关闭PLL时可得到这样的频率);在闪存访问控制寄存器中有一个控制位(FLASH_ACR[3])可以选择这种工作方式。: R3 U& o+ [" f% ?7 |+ J7 ~

2 f7 S5 S4 \; |0 A) D2 M0 _/ U注意:当使用了预取缓冲器和 AHB 时钟的预分频系数不为 ’1’ 时,不能使用半周期访问方式。
% ?' C. b) h8 z2 j- [+ M; k7 m/ c0 e' Y+ m1 l8 ~; f
# G; `: B  I" v) F, J4 T
- P0 r* j% w" {/ w
_T]8Z)V%2VIEX0BYS2831MD.png
PIAPW74SGTJHC43G4%2L$VY.png
赞 收藏 评论0 发布时间:2021-11-30 22:16

举报

0个回答

所属标签

相似技术帖

官网相关资源

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