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

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

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

. ~% l, }; G$ B7 m+ c9 a8 R一、开发环境
# I, e; R& k3 m+ }MDK版本:V5.28
) n/ h/ d! S# c" `单片机:STM32F103RCT6
, ?6 x9 J9 y( S* v' k二、时钟树剖析
$ M% h7 {- G, c5 o1 X! `' f' K: \2 }# P8 M
5}7)N_$J[]~[E6]{CR@H)[Q.png

$ p! k$ F' u. {9 h: [
! }0 U/ N. U8 I, N4 P: k上图就是STM32F10x的时钟树,看着十分复杂,或许有人会问,为什么STM32要把时钟设计的这么复杂?这是因为STM32的外设很多,而且不同的外设需要的时钟是不一样的,例如USB时钟一般需要48MHz,RTC时钟一般是32.768K,APB2总线上的外设最大不超过72MHz,APB1总线外设最大不超过36MHz,如何同时满足这些时钟要求呢?显然如果只设计一种时钟是不可以的,于是就有了上图中复杂的时钟系统。下面我们就来分析下上图的时钟系统。8 N' r& v* _! }, i+ {
  X# _8 H& @4 M2 _: a
首先可以把上图的时钟树划分为以下几个部分:) h/ N/ s5 {# g1 G
5 B( |; F8 k7 I) E  W, H$ P
6KXC8$)[K}1`$~AGTTMA(G9.png

$ U4 T' [- r; T5 ^; G# {) Z7 J( |8 r) @$ ^$ N
_T]8Z)V%2VIEX0BYS2831MD.png

) _5 G1 _  c1 ~* O) M+ n7 i
- n# \8 ]2 l& m基础时钟介绍:; N9 Y" C+ r& H& w" N  A
9 `, w# \8 A! X: V* d/ [5 ]) b
$SEZ~2)7W9YS)29YIGNQ`AE.png

6 l+ |5 w8 \- E/ y9 ?- E* }4 B; U; I- Z1 i: a" n4 ~  E6 m- b% w2 V9 ~
基础时钟并不是官方提出的概念,是我个人的习惯叫法,它主要指的是HSE、LSE、HSI、LSI这四种时钟源,其主要作用如上图所示。9 E5 x% X' j" ^+ h

" _2 r$ m8 I. z8 x; a) [* ]系统时钟的产生:) l0 Y9 A$ f3 t
0 R0 w; J1 r: [0 W0 X3 S+ q9 q4 D* N
ZXIP7BFKM02TZ%`[2YG_XQN.png
( q4 M9 d; S$ [8 L2 ~
2 M8 P1 J2 {" F  X; H* Q
系统时钟的产生有三种方式:1>HSI内部高速时钟,一般为8MHz。 2>HSE外部高速时钟,一般为8MHz晶振。 3>PLL电路,输出频率可任意配置。其中HSI和HSE都属于基础时钟,如果使用PLL时钟作为系统时钟,PLL电路的基准输入必须是HSE或者HSI。
- q2 }; b- b8 j/ y. `* e如果直接使用基础时钟作为系统时钟,那么系统时钟最大频率≤HSE/HSI 如果使用PLL输出时钟作为系统时钟,那么系统时钟最大频率≤72MHz
: m$ w" `+ w  n( q" U
! E. k8 s( F4 v, t下面就以定时器为例说明上述各个时钟之间的供需关系:- S6 \; I3 ^+ \4 c0 G  F2 W
* Y. s2 |' S) _7 l% [7 F8 Q
如果需要使用定时器,那么首先需要开启定时器的时钟,而定时器属于外设,因此需要系统时钟提供时钟给这个外设,对于系统时钟,有两种方式提供,一种是由基础时钟(内部或外部基础时钟源)直接提供,缺点是无法产生更高的频率,时钟源是多高的频率,系统时钟最大不会超过这个频率;第二种是由PLL电路提供,优点是能够产生各种高频稳定的时钟频率,但是也需要基础时钟提供基准信号,且一般情况下STM32F10x系列PLL输出最大不超过72MHz。
: C0 r6 n/ j" X2 B一般来说除RTC外所有的外设时钟(TIM、GPIO、DMA、USART、USB等等)必须由系统时钟提供,但某些特殊外设需要另当别论(以太网、I2S设备等)
% n6 K; u" B  b$ S4 Z
! a# ~$ H+ o3 b4 w9 q1 O& x在STM32时钟树中,还有很多的分频器和倍频器,通过这些分频和倍频器就能产生各种需要的频率,但是只有PLL电路才可以倍频,即产生高于输入频率的频率,例如将8MHz的HSE作为PLL基准输入,最高可以9倍频,产生72MHz的输出频率提供给系统时钟;其余的电路只能进行分频,如TIM、USART等这些外设时钟都是通过系统时钟分频而来,所以它们的最大频率不会超过系统主时钟。: X) S/ l8 ^# H6 _- b( Z

1 o' s2 m/ \) }  E' y) y三、时钟配置流程# E# A4 H9 _  t0 F. n+ X% ]) o$ p
STM32F10x时钟的配置有很多种方式,如果HSE存在,那么可以使用HSE作为PLL输入,也可以不使用,还可以将HSE 128分频作为RTC时钟;当HSE不存在时,可以直接把HSI作为系统主时钟(8MHz),也可以将HSI作为PLL的输入,但此时PLL的最大输出为64MHz。LSE存在时,可以将LSE作为RTC时钟,也可以将LSI作为RTC时钟,看门狗的时钟只能是LSI(40KHz左右)。
; k* K4 P: V8 S8 e8 t* L下面是STM32F10x系统主时钟及总线时钟配置流程:- R+ R* X2 g+ T4 ?+ d7 s5 \
2 c2 |% J& W0 S3 u
TKY9]30$(OE40S(7([JIRBE.png

) `: W& l; q  A+ t* M
1 _$ M( R2 |- I6 e! g1.任意时钟倍频或者分频系数必须在该时钟未使能之前修改,例如PLL倍频系数,当PLL时钟使能后,该倍频系数数被锁定,无法修改,必须先失能PLL,再修改参数,其他时钟亦是如此。
0 `: p! \& t7 R. [1 S9 x$ X0 j* }: V2 B* ]
2.PLL时钟、RTC时钟、系统时钟源切换时,只有当目标时钟就绪时才会切换,否则无法切换。一旦某个时钟源被确定,除非复位,该时钟源不会被停止
. R& d) b9 P3 D4 \4 w& H5 u% S& ]3 T1 O4 @. _; Y" S& F
现根据上述流程,一步一步的进行时钟配置:
! b* R6 j6 u; S# \: k# {尽管时钟树如此复杂,但实际上也就需要配置以下两个寄存器即可!0 `' V0 K3 o6 s# C) H- k! S

, \8 |: `3 k# V0 H9 j0 D7 T
9QOT@@1GNOR)TQDH9DSC{_3.png

) l& `) v: z0 d& T& U" i- _# g( }7 S* r1 K. x8 Y* l% [/ J

5 W% A( [- j/ I, M' R  }, V7 i
)F$VH~58H8C{`NFQB_N_E`S.png
8 q: K8 x$ H' l

6 E' G! s! T8 ^% w) D5 W: pHSE配置(如HSE不存在则时钟错误)
. G$ z/ {* T& H( d& t6 m7 l: P2 L7 I
  1. RCC->CR |= (1<<16);//使能HSE
    ( X5 U8 X5 j$ Q) Y
  2. while((RCC->CR & (1 << 17))==0);//等待HSE就绪% e' m1 g9 ~6 b  y. U. Q% k$ f/ X
  3. RCC->CR |= (1<<19);//如果外部 8-24MHz振荡器就绪,时钟监测器开启。
    * t- a( `, M" B8 }: ^  D

  4. . Q! T& e, A$ p, v
  5. //下面是HSI配置 若有需要可以加上  S. e8 o, |* }0 m5 [; n" _
  6. RCC->CR |= (0x01);//使能HSI8 l( g3 E$ V- _" ^$ e, ~9 @
  7. while((RCC->CR & 0x02)==0);//等待HSI就绪
复制代码
& H4 U1 S/ r; g3 Y1 Q& T, d
FLASH访问配置+ y) C0 o* P4 V( O
  1. FLASH->ACR | = 0x10;//FLASH启用预取缓冲区
    ; \  J2 b9 O/ H; i9 t) |
  2. FLASH->ACR & = 0x03;//清0低2位
    . O7 u/ B( y/ p5 {
  3. FLASH->ACR |=0x02;//等待2个周期
复制代码
0 t8 X) Q) F7 [4 y8 Y  S) z2 X8 H
AHB、APB时钟分频系数配置
( ^3 b- a2 d9 Y+ F3 J
  1. RCC->CFGR = ((0 & 0xf) << 4)|(RCC->CFGR & ~(0xf << 4));//AHB不分频 72M - N/ f: k: c1 L3 Z+ T  Z2 v
  2. RCC->CFGR = ((4 & 0x7) << 8)|(RCC->CFGR & ~(0x7 << 8));//APB1 二分频 36M + y* S2 {, o# S5 F/ Y- F
  3. RCC->CFGR = ((0 & 0x7) << 11)|(RCC->CFGR & ~(0x7 << 11));//APB2 不分频  72M
复制代码

# U7 [% R, [0 R1 A* l" CPLL配置
- J! `" a* o' k: ^, [0 N% p4 T
  1. RCC->CFGR = ((7 & 0xf) << 18)|(RCC->CFGR & ~(0xf << 18));//PLL输出9倍频  8M*9=72M
    . Q0 W9 v% T' k+ c3 ]' Q
  2. RCC->CFGR = ((1 & 0x01) << 16)|(RCC->CFGR & ~(0x01 << 16));//PLL时钟源选择HSE
    , T2 G5 V6 L6 Q8 }0 D) B. q
  3. RCC->CFGR = ((0 & 0x01) << 17)|(RCC->CFGR & ~(0x01 << 17));//HSE不分频接入PLL
    0 X  L; i4 |* B! k
  4. RCC->CR |= (1<<24);//使能PLL9 W; |+ E, Y  M# y/ W# @* E& [
  5. while((RCC->CR & (1 << 25))==0);//等待PLL就绪
复制代码

) v& v1 p/ P% O; @% j- I% d系统时钟配置/ F" ^' ]7 f+ O0 i4 p7 q; }' V8 Y9 J
  1. RCC->CFGR = (0x02 & 0x03)|(RCC->CFGR & ~(0x03));//系统时钟源选择PLL" k2 o1 r" {5 a
  2. while((RCC->CFGR & 0x0c)!=0x08);//等待PLL作为系统时钟源就绪
复制代码
4 q+ I- E3 K( [1 X" a& ?8 X  l$ r% Q
这样系统时钟就配置完成了,如果HSE接的是8MHz晶振,那么SYSCLK=AHB=APB2=72MHz,APB1=36MHz 。这里并没有开启RTC、USB等时钟,大家可以根据需要自行开启。
9 Z+ f; F5 R- F5 N8 j: }对系统时钟的初始化,在STM32F10x的库函数system_stm32f10x.c文件中:SystemInit函数也有类似的实现方法,大家也可以参考下。; j2 R$ W! D3 [8 K" W
, V  {7 R/ g, v1 |
四、备注3 k5 F' [$ @  L; }( f% w% |8 L
系统复位后,HSI 振荡器被选为系统时钟。/ i, ]( Y; \; E- r
3 C5 p% V* K1 {' {/ D
时钟安全系统可以通过软件被激活。一旦其被激活,时钟监测器将在 HSE 振荡器启动延迟后被使能,并在 HSE 时钟关闭后关闭。如果 HSE 时钟发生故障,此振荡器自动地被关闭,时钟失效事件将被送到高级定时器 TIM1 的断路输入端,并产生时钟安全中断 CSSI,允许软件完成营救操作。此 CSSI 中断被连接到 Cortex-M3 NMI 的中断。
; M2 T1 [, S4 c3 p( M( U3 c2 B; E4 R4 l5 {. n
如果独立看门狗已经由硬件选项或软件启动,LSI 振荡器将被强制在打开状态,并且不能被关闭。在 LSI 振荡器稳定后,时钟供应给 IWDG。
' I( r/ G  E3 {% R5 L9 U" d& k* F9 ~/ v6 f- {
FLASH预取缓冲器:! P" N4 Y$ Q  ]: u+ c

! _3 D- q7 s, U8 o$ ^+ A复位后预取缓冲器处于开启状态
' @* A% D; w( P/ z0 r. W% r: z  B+ y. ?* w4 O
只有当SYSCLK低于24MHz时才能转换预取缓冲器的开启/关闭状态。通常在系统的初始化程序中开启或关闭预取缓冲器,此时微控制器运行于内部的8MHz阻容振荡器(HSI)。! l$ T1 d- ?! v" C+ C

! \9 _! H; u0 ^* \注意:当 AHB 时钟的预分频系数不为 ’1’ 时,必须打开预取缓冲器 (FLASH_ACR[4]=1) 。如果在系统中没有高频率的时钟,即HCLK频率较低时,闪存的访问只需半个HCLK周期(半周期的闪存访问只能在时钟频率低于8MHz时进行,使用HSI或HSE并且关闭PLL时可得到这样的频率);在闪存访问控制寄存器中有一个控制位(FLASH_ACR[3])可以选择这种工作方式。
' q& T2 D1 X* w7 e' i( B5 q' j. x& C1 P8 i; O  ?
注意:当使用了预取缓冲器和 AHB 时钟的预分频系数不为 ’1’ 时,不能使用半周期访问方式。
" J; u) W: R( Q$ O/ Y7 _6 O2 C# X. \4 f
/ H( y% s# t: f4 m9 t

: E5 s; `1 _6 f6 W& E2 X' @
_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 手机版