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

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

[复制链接]
STMCU小助手 发布时间:2021-11-30 22:16
实际上,对于STM32F10x系列的芯片,如果使用库函数方式开发,芯片的时钟初始化函数已经写好,并且在启动文件(例如startup_stm32f10x_hd.s)中被自动调用,在进入main函数之前,系统以及外设时钟均配置完成,main程序中不需要对时钟再进行任何配置,直接编写应用程序即可。但是作为一个底层驱动玩家必须要打破砂锅问到底,看看STM32F10x系列芯片的时钟系统到底是怎么样的以及如何配置时钟,下文将着重分析STM32F10x的时钟系统以及用寄存器方式从零开始一步一步配置时钟。1 j  W! o2 |3 Q# L- z

( q# x  m9 d* I9 a5 L: ?" P' Q$ u一、开发环境
" A1 J' W% d! K5 e3 JMDK版本:V5.28
/ M6 y7 D! _2 ~, w# q! d+ t单片机:STM32F103RCT6  H2 R& R0 f( ^. R$ z. j+ U
二、时钟树剖析
/ p- C% r% s9 G9 V/ s2 L) ~4 M
! a" ?& @$ l' R# m
5}7)N_$J[]~[E6]{CR@H)[Q.png

# h; [! _3 Y8 }! t3 n7 X2 Q9 r, s8 S8 H# ~6 a& F0 ?8 @# N
上图就是STM32F10x的时钟树,看着十分复杂,或许有人会问,为什么STM32要把时钟设计的这么复杂?这是因为STM32的外设很多,而且不同的外设需要的时钟是不一样的,例如USB时钟一般需要48MHz,RTC时钟一般是32.768K,APB2总线上的外设最大不超过72MHz,APB1总线外设最大不超过36MHz,如何同时满足这些时钟要求呢?显然如果只设计一种时钟是不可以的,于是就有了上图中复杂的时钟系统。下面我们就来分析下上图的时钟系统。
) G7 ?: l$ p* X( |( |& O
/ k0 A% A3 }# d* m1 t3 t3 h首先可以把上图的时钟树划分为以下几个部分:
* A: O% |* G( e1 g! B3 i
8 _6 Z4 A, O  [6 ~
6KXC8$)[K}1`$~AGTTMA(G9.png
) ?' ^  h# t' y6 I5 {
+ Z- V0 Q2 t6 _! t0 U
_T]8Z)V%2VIEX0BYS2831MD.png
% _" Y! V" K" X+ w) N; d2 \$ c3 K

  {2 [! L' ]! v8 L& I4 q基础时钟介绍:4 a, y* j! _" A# d! B; y0 Y0 L) d; Q

9 f  t' X" H- K3 T" L' u
$SEZ~2)7W9YS)29YIGNQ`AE.png

, i6 Q. k. \  `; W( m- j3 T9 Q# b, Q: o4 @9 }; {! m  u
基础时钟并不是官方提出的概念,是我个人的习惯叫法,它主要指的是HSE、LSE、HSI、LSI这四种时钟源,其主要作用如上图所示。
- e. y2 n  N; h# T9 U: m. p/ N( [/ g2 ^4 l0 }0 j4 Z
系统时钟的产生:) \, B8 X+ c8 S- H9 X
) T" I7 Z/ R, C9 Q  A% }
ZXIP7BFKM02TZ%`[2YG_XQN.png

$ S/ y1 \- }/ c- f$ P3 w/ b9 L5 H/ {+ Z# F
系统时钟的产生有三种方式:1>HSI内部高速时钟,一般为8MHz。 2>HSE外部高速时钟,一般为8MHz晶振。 3>PLL电路,输出频率可任意配置。其中HSI和HSE都属于基础时钟,如果使用PLL时钟作为系统时钟,PLL电路的基准输入必须是HSE或者HSI。2 v9 E, S, m, @0 Y/ w! y
如果直接使用基础时钟作为系统时钟,那么系统时钟最大频率≤HSE/HSI 如果使用PLL输出时钟作为系统时钟,那么系统时钟最大频率≤72MHz
2 O* x3 O( c' }2 ~. e# k! Z+ C! `% r# H$ H0 p
下面就以定时器为例说明上述各个时钟之间的供需关系:5 Q* b( T! x5 B$ D2 h9 e2 b

4 O6 a1 ]& D  V. w1 Y  }& i: q如果需要使用定时器,那么首先需要开启定时器的时钟,而定时器属于外设,因此需要系统时钟提供时钟给这个外设,对于系统时钟,有两种方式提供,一种是由基础时钟(内部或外部基础时钟源)直接提供,缺点是无法产生更高的频率,时钟源是多高的频率,系统时钟最大不会超过这个频率;第二种是由PLL电路提供,优点是能够产生各种高频稳定的时钟频率,但是也需要基础时钟提供基准信号,且一般情况下STM32F10x系列PLL输出最大不超过72MHz。: h/ j6 u8 Z  Q+ a( ~5 V+ e
一般来说除RTC外所有的外设时钟(TIM、GPIO、DMA、USART、USB等等)必须由系统时钟提供,但某些特殊外设需要另当别论(以太网、I2S设备等); a+ ]3 L5 w2 q
$ p7 v8 O. U+ J; ~' w/ s# T# a& r& \" k
在STM32时钟树中,还有很多的分频器和倍频器,通过这些分频和倍频器就能产生各种需要的频率,但是只有PLL电路才可以倍频,即产生高于输入频率的频率,例如将8MHz的HSE作为PLL基准输入,最高可以9倍频,产生72MHz的输出频率提供给系统时钟;其余的电路只能进行分频,如TIM、USART等这些外设时钟都是通过系统时钟分频而来,所以它们的最大频率不会超过系统主时钟。
  x$ n' E$ s2 T5 {' g
0 ?! W2 i. E; K& F三、时钟配置流程( n9 C/ ]) K+ W0 A
STM32F10x时钟的配置有很多种方式,如果HSE存在,那么可以使用HSE作为PLL输入,也可以不使用,还可以将HSE 128分频作为RTC时钟;当HSE不存在时,可以直接把HSI作为系统主时钟(8MHz),也可以将HSI作为PLL的输入,但此时PLL的最大输出为64MHz。LSE存在时,可以将LSE作为RTC时钟,也可以将LSI作为RTC时钟,看门狗的时钟只能是LSI(40KHz左右)。
1 O: B+ i1 S4 X! A8 K" Z7 L下面是STM32F10x系统主时钟及总线时钟配置流程:
$ K; ^; f( a& ]. d, O
; l  Q# B3 k. `9 ~2 v9 u9 ^
TKY9]30$(OE40S(7([JIRBE.png
8 N& s; h# E5 F2 r
$ h" @; c6 Z  a! K6 ?6 A. {
1.任意时钟倍频或者分频系数必须在该时钟未使能之前修改,例如PLL倍频系数,当PLL时钟使能后,该倍频系数数被锁定,无法修改,必须先失能PLL,再修改参数,其他时钟亦是如此。. z3 N% Z) i. O! S  [2 V& c: y* u
# J+ i/ I8 S2 H( B) [. \
2.PLL时钟、RTC时钟、系统时钟源切换时,只有当目标时钟就绪时才会切换,否则无法切换。一旦某个时钟源被确定,除非复位,该时钟源不会被停止
- x( w% H' H- h  L
4 |/ O7 ?7 ^/ V$ ?" r现根据上述流程,一步一步的进行时钟配置:0 t- p( D0 Q. h% Z( M8 Y0 U7 F+ o
尽管时钟树如此复杂,但实际上也就需要配置以下两个寄存器即可!& |/ E" Q, N- K* r% ~5 n  B
$ G' v5 X" l4 F' R
9QOT@@1GNOR)TQDH9DSC{_3.png
/ E$ E! U6 F7 Q- t% @
7 r$ Z  O; Z1 D2 S  H

/ S3 t; x4 Z/ q" ?: M
)F$VH~58H8C{`NFQB_N_E`S.png
& O  ^( P) R& c' `

9 F$ l) L  Q9 p. s2 DHSE配置(如HSE不存在则时钟错误)
& e) V7 R" E! U5 Y& T" z+ ^1 W2 q" u
  1. RCC->CR |= (1<<16);//使能HSE1 j2 M5 A. q+ k" {1 T
  2. while((RCC->CR & (1 << 17))==0);//等待HSE就绪
    9 p$ B" w& X0 o, V
  3. RCC->CR |= (1<<19);//如果外部 8-24MHz振荡器就绪,时钟监测器开启。
    * k# O6 H7 w5 b* h

  4. / s! ?' A% [6 t* A4 ?  Q
  5. //下面是HSI配置 若有需要可以加上- c9 G/ \/ ^# Z, V
  6. RCC->CR |= (0x01);//使能HSI2 n2 `/ w/ @1 e( p1 v3 Z
  7. while((RCC->CR & 0x02)==0);//等待HSI就绪
复制代码

" A: z' y" ^- r) T: nFLASH访问配置" [; R# a7 N  ?$ I
  1. FLASH->ACR | = 0x10;//FLASH启用预取缓冲区
    : D! d- e4 a2 C+ N6 S
  2. FLASH->ACR & = 0x03;//清0低2位( k; h: {3 }* Z8 Z" c( P! `0 H0 x
  3. FLASH->ACR |=0x02;//等待2个周期
复制代码

$ V. C% ?0 C; i# u2 \: S  |; PAHB、APB时钟分频系数配置9 c# a  J. U4 \! s$ J
  1. RCC->CFGR = ((0 & 0xf) << 4)|(RCC->CFGR & ~(0xf << 4));//AHB不分频 72M : Z6 a$ J* t# a  O! H5 `; n
  2. RCC->CFGR = ((4 & 0x7) << 8)|(RCC->CFGR & ~(0x7 << 8));//APB1 二分频 36M
    " G2 o1 y. f' J3 o
  3. RCC->CFGR = ((0 & 0x7) << 11)|(RCC->CFGR & ~(0x7 << 11));//APB2 不分频  72M
复制代码
4 n  L6 A1 B8 |6 F5 n8 J
PLL配置
7 f1 M0 |, m7 y9 H+ }, r% s* W
  1. RCC->CFGR = ((7 & 0xf) << 18)|(RCC->CFGR & ~(0xf << 18));//PLL输出9倍频  8M*9=72M/ q) g# S* ~$ ], K7 U
  2. RCC->CFGR = ((1 & 0x01) << 16)|(RCC->CFGR & ~(0x01 << 16));//PLL时钟源选择HSE& ~: m$ j0 F# D' Q
  3. RCC->CFGR = ((0 & 0x01) << 17)|(RCC->CFGR & ~(0x01 << 17));//HSE不分频接入PLL. ^2 D# Q* l! t9 Y5 E: l# Q
  4. RCC->CR |= (1<<24);//使能PLL
    " o) N1 \, z) F/ w) ^( o
  5. while((RCC->CR & (1 << 25))==0);//等待PLL就绪
复制代码
) y6 ?/ R: G. w0 @# \
系统时钟配置
# m! h! i# F& U5 b0 ?
  1. RCC->CFGR = (0x02 & 0x03)|(RCC->CFGR & ~(0x03));//系统时钟源选择PLL# R8 C9 e1 |! \" j
  2. while((RCC->CFGR & 0x0c)!=0x08);//等待PLL作为系统时钟源就绪
复制代码

1 _! E  [* g- h% M4 X7 R/ p. _, D这样系统时钟就配置完成了,如果HSE接的是8MHz晶振,那么SYSCLK=AHB=APB2=72MHz,APB1=36MHz 。这里并没有开启RTC、USB等时钟,大家可以根据需要自行开启。
7 n) A! _5 q' ^, N# c1 a. r" t对系统时钟的初始化,在STM32F10x的库函数system_stm32f10x.c文件中:SystemInit函数也有类似的实现方法,大家也可以参考下。, w& }' J% Y  Y' f  j: z/ ?

% m& Z, a! C/ d; S( I" A/ e四、备注0 {; u: j5 u) Y" C
系统复位后,HSI 振荡器被选为系统时钟。
) z+ z2 G, ?5 ^0 y2 Q( ~0 h" _& G0 C
时钟安全系统可以通过软件被激活。一旦其被激活,时钟监测器将在 HSE 振荡器启动延迟后被使能,并在 HSE 时钟关闭后关闭。如果 HSE 时钟发生故障,此振荡器自动地被关闭,时钟失效事件将被送到高级定时器 TIM1 的断路输入端,并产生时钟安全中断 CSSI,允许软件完成营救操作。此 CSSI 中断被连接到 Cortex-M3 NMI 的中断。( [0 m9 z/ W/ v6 U! s# C) V8 K

% t6 a) Z* S& s# \# v1 E如果独立看门狗已经由硬件选项或软件启动,LSI 振荡器将被强制在打开状态,并且不能被关闭。在 LSI 振荡器稳定后,时钟供应给 IWDG。
6 e  f% e/ I; Z5 E5 C: i  n/ X
1 F5 h) l. \* p% m0 }1 @FLASH预取缓冲器:
# ]5 s8 Y, X1 t, U' h  f/ J3 B0 w/ K" t  [, |
复位后预取缓冲器处于开启状态+ X8 G# m3 }; w( m7 y' v

9 Z1 Q6 x1 d; F# ?9 O, ^只有当SYSCLK低于24MHz时才能转换预取缓冲器的开启/关闭状态。通常在系统的初始化程序中开启或关闭预取缓冲器,此时微控制器运行于内部的8MHz阻容振荡器(HSI)。7 M/ Y8 ?7 ~/ W9 C7 |) B

% n6 o& L( {. x" u! ?9 k8 {注意:当 AHB 时钟的预分频系数不为 ’1’ 时,必须打开预取缓冲器 (FLASH_ACR[4]=1) 。如果在系统中没有高频率的时钟,即HCLK频率较低时,闪存的访问只需半个HCLK周期(半周期的闪存访问只能在时钟频率低于8MHz时进行,使用HSI或HSE并且关闭PLL时可得到这样的频率);在闪存访问控制寄存器中有一个控制位(FLASH_ACR[3])可以选择这种工作方式。
, r4 g% k+ I+ B5 W3 h4 u+ g% h- Z5 {! ]+ _) N8 t1 {& B( c& A
注意:当使用了预取缓冲器和 AHB 时钟的预分频系数不为 ’1’ 时,不能使用半周期访问方式。
! U8 e$ K; x! l& t9 C4 h) K5 ?, g% k# ~$ I0 o% s

& v. F. M0 P/ R
8 T  e7 \4 Y, w2 k! x
_T]8Z)V%2VIEX0BYS2831MD.png
PIAPW74SGTJHC43G4%2L$VY.png
收藏 评论0 发布时间:2021-11-30 22:16

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版