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

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

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

  O) C' ]$ N. _6 H: a/ v一、开发环境
  H4 ]! W0 F; p; pMDK版本:V5.28
6 Z# D+ P: C( o) T* ]单片机:STM32F103RCT6
& Y9 c. O# b+ e9 E二、时钟树剖析
5 f0 O" b, s  H* k! q7 b& U; Y& d, f5 f# n
5}7)N_$J[]~[E6]{CR@H)[Q.png

) J& G4 i2 L. q' Z7 i: F6 Y" O5 g, L! T
上图就是STM32F10x的时钟树,看着十分复杂,或许有人会问,为什么STM32要把时钟设计的这么复杂?这是因为STM32的外设很多,而且不同的外设需要的时钟是不一样的,例如USB时钟一般需要48MHz,RTC时钟一般是32.768K,APB2总线上的外设最大不超过72MHz,APB1总线外设最大不超过36MHz,如何同时满足这些时钟要求呢?显然如果只设计一种时钟是不可以的,于是就有了上图中复杂的时钟系统。下面我们就来分析下上图的时钟系统。
% q  q/ z* }# D
: W" }) a( j1 z/ r6 l3 r8 Z首先可以把上图的时钟树划分为以下几个部分:- M4 G6 s: J  C: U; q1 l* H/ P1 M& g# \
) `- [- {8 W0 ^: c0 B
6KXC8$)[K}1`$~AGTTMA(G9.png
6 h3 A8 O; R* f, v$ J4 V2 U+ `& x

7 H. @2 ~4 s" b( f( Z/ w- X
_T]8Z)V%2VIEX0BYS2831MD.png
3 ]6 ^( x2 ~* v$ d
! r) x0 q% t% e% X2 x
基础时钟介绍:' Z1 a# d$ G3 m1 T3 r# N0 y

2 w6 Q8 a, Z7 m5 O
$SEZ~2)7W9YS)29YIGNQ`AE.png
- E/ m! _+ |  Y. X- w! G

+ C5 i2 z0 ?4 `+ u5 p; m- G基础时钟并不是官方提出的概念,是我个人的习惯叫法,它主要指的是HSE、LSE、HSI、LSI这四种时钟源,其主要作用如上图所示。" h) T6 [7 w- F
6 p' c& d" z5 {3 u8 h9 g
系统时钟的产生:8 f$ S( K" g: o1 c/ ~

) x% H: X# i1 q
ZXIP7BFKM02TZ%`[2YG_XQN.png
* B5 X  ?+ v7 f1 v( T$ F
$ Y5 C. @8 V% L, [) o: B
系统时钟的产生有三种方式:1>HSI内部高速时钟,一般为8MHz。 2>HSE外部高速时钟,一般为8MHz晶振。 3>PLL电路,输出频率可任意配置。其中HSI和HSE都属于基础时钟,如果使用PLL时钟作为系统时钟,PLL电路的基准输入必须是HSE或者HSI。3 U1 {5 T; a& V: S4 M, U) a+ r
如果直接使用基础时钟作为系统时钟,那么系统时钟最大频率≤HSE/HSI 如果使用PLL输出时钟作为系统时钟,那么系统时钟最大频率≤72MHz
% k1 j; l. [( V3 {. W$ L
+ h: g" c5 A0 E下面就以定时器为例说明上述各个时钟之间的供需关系:, n+ }: k6 ]' f) {7 L" h- M+ S
& \4 P3 x5 F5 T/ G$ O3 w4 {
如果需要使用定时器,那么首先需要开启定时器的时钟,而定时器属于外设,因此需要系统时钟提供时钟给这个外设,对于系统时钟,有两种方式提供,一种是由基础时钟(内部或外部基础时钟源)直接提供,缺点是无法产生更高的频率,时钟源是多高的频率,系统时钟最大不会超过这个频率;第二种是由PLL电路提供,优点是能够产生各种高频稳定的时钟频率,但是也需要基础时钟提供基准信号,且一般情况下STM32F10x系列PLL输出最大不超过72MHz。; z: W2 M* G/ P% K9 u% _* K
一般来说除RTC外所有的外设时钟(TIM、GPIO、DMA、USART、USB等等)必须由系统时钟提供,但某些特殊外设需要另当别论(以太网、I2S设备等)
) s+ X5 E# p, n! r9 |+ O7 b9 T3 A7 q% l) [
在STM32时钟树中,还有很多的分频器和倍频器,通过这些分频和倍频器就能产生各种需要的频率,但是只有PLL电路才可以倍频,即产生高于输入频率的频率,例如将8MHz的HSE作为PLL基准输入,最高可以9倍频,产生72MHz的输出频率提供给系统时钟;其余的电路只能进行分频,如TIM、USART等这些外设时钟都是通过系统时钟分频而来,所以它们的最大频率不会超过系统主时钟。
8 Q6 d: @+ N0 w1 d/ u3 i: O2 K
* l1 M1 J- |4 H5 W三、时钟配置流程
: }6 ?; P& c( X- i+ e+ ]' B# @STM32F10x时钟的配置有很多种方式,如果HSE存在,那么可以使用HSE作为PLL输入,也可以不使用,还可以将HSE 128分频作为RTC时钟;当HSE不存在时,可以直接把HSI作为系统主时钟(8MHz),也可以将HSI作为PLL的输入,但此时PLL的最大输出为64MHz。LSE存在时,可以将LSE作为RTC时钟,也可以将LSI作为RTC时钟,看门狗的时钟只能是LSI(40KHz左右)。1 [) V; o  A# A
下面是STM32F10x系统主时钟及总线时钟配置流程:
/ G% v+ V! S; k  I
3 U1 ]" P7 `& E7 y  k# r
TKY9]30$(OE40S(7([JIRBE.png

2 `7 E8 L1 p& @7 e7 D5 r+ p
# v. Q, u% N8 Z/ z8 E1.任意时钟倍频或者分频系数必须在该时钟未使能之前修改,例如PLL倍频系数,当PLL时钟使能后,该倍频系数数被锁定,无法修改,必须先失能PLL,再修改参数,其他时钟亦是如此。
; l6 l) n, }8 q/ ?0 D, _
. h8 Z( m' {* L0 p! ?8 m2.PLL时钟、RTC时钟、系统时钟源切换时,只有当目标时钟就绪时才会切换,否则无法切换。一旦某个时钟源被确定,除非复位,该时钟源不会被停止
2 I# ^% Z9 V: ~) p) x
, H; G5 x# Q: {- t9 a# {现根据上述流程,一步一步的进行时钟配置:
" E* @& e" @6 Z0 f尽管时钟树如此复杂,但实际上也就需要配置以下两个寄存器即可!
7 f: }- v0 h  M7 n  q/ R5 R. L9 R/ R$ z( I, d
9QOT@@1GNOR)TQDH9DSC{_3.png
* v* U9 G/ K8 c9 c4 k5 @5 d, u
+ P, _) [) |: p+ Z7 u
% C1 X" V( d. r7 \
)F$VH~58H8C{`NFQB_N_E`S.png

; w$ A+ v3 I! S7 L7 @. O: K' K
6 [! [  A* q6 A; z+ z' c9 A3 LHSE配置(如HSE不存在则时钟错误)
" x( x- y, s3 V% A
  1. RCC->CR |= (1<<16);//使能HSE7 e) Y4 v6 W1 K* D. m
  2. while((RCC->CR & (1 << 17))==0);//等待HSE就绪, A; K2 O) v% N, Y  [% F2 O
  3. RCC->CR |= (1<<19);//如果外部 8-24MHz振荡器就绪,时钟监测器开启。
    ) T9 r+ z, [0 e  J  E

  4. 0 u6 X+ c) c6 U5 t; k  z
  5. //下面是HSI配置 若有需要可以加上
    8 m* U( D; [2 T( o1 E. ~% t. ]' W
  6. RCC->CR |= (0x01);//使能HSI/ F! R+ n( _3 a, E- [
  7. while((RCC->CR & 0x02)==0);//等待HSI就绪
复制代码
- y1 [: d" i  ]  A8 i# h( l
FLASH访问配置
2 o' f, _' C  Q+ C$ x1 v& @& J4 O  M
  1. FLASH->ACR | = 0x10;//FLASH启用预取缓冲区" j( F( }" w( o8 B0 U
  2. FLASH->ACR & = 0x03;//清0低2位2 e) k% o) s: O0 D' e5 [
  3. FLASH->ACR |=0x02;//等待2个周期
复制代码

. E# G) G) o3 r0 N% J9 CAHB、APB时钟分频系数配置
+ t% H1 z  ?! U3 |! N) G. @# @
  1. RCC->CFGR = ((0 & 0xf) << 4)|(RCC->CFGR & ~(0xf << 4));//AHB不分频 72M
    : S4 a7 J( o$ K8 _8 P
  2. RCC->CFGR = ((4 & 0x7) << 8)|(RCC->CFGR & ~(0x7 << 8));//APB1 二分频 36M 2 y3 F& ]" D, p1 _3 \, r8 [7 R+ S
  3. RCC->CFGR = ((0 & 0x7) << 11)|(RCC->CFGR & ~(0x7 << 11));//APB2 不分频  72M
复制代码

% P) L- ]- A7 {* H3 rPLL配置. e7 Q6 n& s" ?& J# s
  1. RCC->CFGR = ((7 & 0xf) << 18)|(RCC->CFGR & ~(0xf << 18));//PLL输出9倍频  8M*9=72M5 U& S9 L3 c5 t. u& W
  2. RCC->CFGR = ((1 & 0x01) << 16)|(RCC->CFGR & ~(0x01 << 16));//PLL时钟源选择HSE" m& j- ]; S/ Y6 }% ~
  3. RCC->CFGR = ((0 & 0x01) << 17)|(RCC->CFGR & ~(0x01 << 17));//HSE不分频接入PLL
    * W6 ~: _' Q3 p$ ?. L
  4. RCC->CR |= (1<<24);//使能PLL( f7 v, y9 n+ x+ ^4 V
  5. while((RCC->CR & (1 << 25))==0);//等待PLL就绪
复制代码

. p! f6 z6 g9 }4 g3 D0 d系统时钟配置
" g  I4 e" V4 c. H5 C
  1. RCC->CFGR = (0x02 & 0x03)|(RCC->CFGR & ~(0x03));//系统时钟源选择PLL; R3 [% m6 a7 O9 |* K4 U
  2. while((RCC->CFGR & 0x0c)!=0x08);//等待PLL作为系统时钟源就绪
复制代码
  H# P0 o' T( F, E" d4 Z
这样系统时钟就配置完成了,如果HSE接的是8MHz晶振,那么SYSCLK=AHB=APB2=72MHz,APB1=36MHz 。这里并没有开启RTC、USB等时钟,大家可以根据需要自行开启。7 F6 X: ^& Z' n- a' |
对系统时钟的初始化,在STM32F10x的库函数system_stm32f10x.c文件中:SystemInit函数也有类似的实现方法,大家也可以参考下。' y4 v4 j) G6 W2 Z+ o2 U
" H% x) v0 U* o8 F) X
四、备注
5 e3 G- I3 ?* o7 @& u0 m系统复位后,HSI 振荡器被选为系统时钟。: V6 u1 A8 }, H2 N1 p

# I% d1 V7 W8 F3 U* L8 i) }1 J时钟安全系统可以通过软件被激活。一旦其被激活,时钟监测器将在 HSE 振荡器启动延迟后被使能,并在 HSE 时钟关闭后关闭。如果 HSE 时钟发生故障,此振荡器自动地被关闭,时钟失效事件将被送到高级定时器 TIM1 的断路输入端,并产生时钟安全中断 CSSI,允许软件完成营救操作。此 CSSI 中断被连接到 Cortex-M3 NMI 的中断。$ n/ @! ?' P6 D/ M# e' E6 n
; {  B( F' u% `# K' N
如果独立看门狗已经由硬件选项或软件启动,LSI 振荡器将被强制在打开状态,并且不能被关闭。在 LSI 振荡器稳定后,时钟供应给 IWDG。; g3 e" g! V- Q

' C1 I3 m7 w$ J* A% f4 |FLASH预取缓冲器:
6 V" ]6 Z. b4 B* r" @1 e; ]  j" U$ _& h
复位后预取缓冲器处于开启状态
6 \/ d/ y& J, R+ s7 A( R" d3 `2 Z% V0 S( d% y( q
只有当SYSCLK低于24MHz时才能转换预取缓冲器的开启/关闭状态。通常在系统的初始化程序中开启或关闭预取缓冲器,此时微控制器运行于内部的8MHz阻容振荡器(HSI)。
5 S5 z* C+ E( s+ R7 B
8 D9 Z8 J& M* B- ~1 @2 x" G" l5 t注意:当 AHB 时钟的预分频系数不为 ’1’ 时,必须打开预取缓冲器 (FLASH_ACR[4]=1) 。如果在系统中没有高频率的时钟,即HCLK频率较低时,闪存的访问只需半个HCLK周期(半周期的闪存访问只能在时钟频率低于8MHz时进行,使用HSI或HSE并且关闭PLL时可得到这样的频率);在闪存访问控制寄存器中有一个控制位(FLASH_ACR[3])可以选择这种工作方式。
# X. X& j7 x" }$ y5 p0 `1 [  V$ H- Z# N
注意:当使用了预取缓冲器和 AHB 时钟的预分频系数不为 ’1’ 时,不能使用半周期访问方式。
4 a1 ?1 A) R4 N  W; l6 t; N: ~) ~) T! l+ Y! W5 k
" y# Z' E2 j0 N9 Y* x' Z
" E, T8 Q+ X1 U; g3 `* N
_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 手机版