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

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

[复制链接]
STMCU小助手 发布时间:2021-11-30 22:16
实际上,对于STM32F10x系列的芯片,如果使用库函数方式开发,芯片的时钟初始化函数已经写好,并且在启动文件(例如startup_stm32f10x_hd.s)中被自动调用,在进入main函数之前,系统以及外设时钟均配置完成,main程序中不需要对时钟再进行任何配置,直接编写应用程序即可。但是作为一个底层驱动玩家必须要打破砂锅问到底,看看STM32F10x系列芯片的时钟系统到底是怎么样的以及如何配置时钟,下文将着重分析STM32F10x的时钟系统以及用寄存器方式从零开始一步一步配置时钟。
; f$ g0 m$ K+ i% m1 J: M2 p# o% }2 G- S+ W5 `
一、开发环境$ j% Y- E; |  Z/ b% k2 B5 J
MDK版本:V5.28
7 M  X) r( c* n9 V- G5 z4 `. F单片机:STM32F103RCT6% S- y$ ~, B. t- `
二、时钟树剖析5 B$ H: q1 z9 p& s
3 g! w/ i" y( q6 \" m) i( Z$ ^
5}7)N_$J[]~[E6]{CR@H)[Q.png
- y6 ?  }& x# z$ @
" U: R9 _: F( @; f+ m
上图就是STM32F10x的时钟树,看着十分复杂,或许有人会问,为什么STM32要把时钟设计的这么复杂?这是因为STM32的外设很多,而且不同的外设需要的时钟是不一样的,例如USB时钟一般需要48MHz,RTC时钟一般是32.768K,APB2总线上的外设最大不超过72MHz,APB1总线外设最大不超过36MHz,如何同时满足这些时钟要求呢?显然如果只设计一种时钟是不可以的,于是就有了上图中复杂的时钟系统。下面我们就来分析下上图的时钟系统。; {' @8 r7 o2 H

+ [6 Z+ O* e8 `( H; T2 h+ h首先可以把上图的时钟树划分为以下几个部分:+ c% P3 ^$ h* ?9 ^6 U
* M# k+ _3 H, @% _! l0 a0 m4 r1 q
6KXC8$)[K}1`$~AGTTMA(G9.png

, o+ c) e6 ~0 u1 Y9 B) a% ?
6 y- Y2 V* t1 {4 r" B+ Z
_T]8Z)V%2VIEX0BYS2831MD.png
! j4 g/ Z' t& B
. N: t6 z/ X2 L9 v) x$ ^% @
基础时钟介绍:7 y7 e( _5 v5 M! m/ i' M4 o

, {# Q/ Q2 g* v0 q) v8 b
$SEZ~2)7W9YS)29YIGNQ`AE.png

  \. w; ]: h$ r( @2 {0 `# @' b* m# `; w$ L- `  g8 i3 W
基础时钟并不是官方提出的概念,是我个人的习惯叫法,它主要指的是HSE、LSE、HSI、LSI这四种时钟源,其主要作用如上图所示。) v( b7 Y6 V7 H3 f' o& S* }. o

' k7 J# m2 F, }2 D1 o系统时钟的产生:
2 \  p" V2 v) k) r  n. d# v  j% Y6 Q# Q6 G& _1 f/ T' e% {, U
ZXIP7BFKM02TZ%`[2YG_XQN.png
6 F0 }4 y' K  L$ l
! K) e1 ~- n+ D, R
系统时钟的产生有三种方式:1>HSI内部高速时钟,一般为8MHz。 2>HSE外部高速时钟,一般为8MHz晶振。 3>PLL电路,输出频率可任意配置。其中HSI和HSE都属于基础时钟,如果使用PLL时钟作为系统时钟,PLL电路的基准输入必须是HSE或者HSI。+ I. D0 S; }8 V
如果直接使用基础时钟作为系统时钟,那么系统时钟最大频率≤HSE/HSI 如果使用PLL输出时钟作为系统时钟,那么系统时钟最大频率≤72MHz
" R2 X: [  v5 g9 V9 c* s" O- ]1 o% n- K
下面就以定时器为例说明上述各个时钟之间的供需关系:
. f6 X9 V$ H( m7 B- P) G5 n! M. w* ]- \% p, \" ^4 S$ l
如果需要使用定时器,那么首先需要开启定时器的时钟,而定时器属于外设,因此需要系统时钟提供时钟给这个外设,对于系统时钟,有两种方式提供,一种是由基础时钟(内部或外部基础时钟源)直接提供,缺点是无法产生更高的频率,时钟源是多高的频率,系统时钟最大不会超过这个频率;第二种是由PLL电路提供,优点是能够产生各种高频稳定的时钟频率,但是也需要基础时钟提供基准信号,且一般情况下STM32F10x系列PLL输出最大不超过72MHz。
+ _+ A2 t9 @' S% w一般来说除RTC外所有的外设时钟(TIM、GPIO、DMA、USART、USB等等)必须由系统时钟提供,但某些特殊外设需要另当别论(以太网、I2S设备等)% ]8 z  ?' _  P) u% y2 @" `
, o7 U! h6 i4 O' u5 K4 M0 u' L
在STM32时钟树中,还有很多的分频器和倍频器,通过这些分频和倍频器就能产生各种需要的频率,但是只有PLL电路才可以倍频,即产生高于输入频率的频率,例如将8MHz的HSE作为PLL基准输入,最高可以9倍频,产生72MHz的输出频率提供给系统时钟;其余的电路只能进行分频,如TIM、USART等这些外设时钟都是通过系统时钟分频而来,所以它们的最大频率不会超过系统主时钟。. K( j2 u; a8 @; m! a# y: K

: l# ~& o& Q7 b, o* T9 j三、时钟配置流程
) X% G# ^; c3 s+ t6 S1 V. P2 }STM32F10x时钟的配置有很多种方式,如果HSE存在,那么可以使用HSE作为PLL输入,也可以不使用,还可以将HSE 128分频作为RTC时钟;当HSE不存在时,可以直接把HSI作为系统主时钟(8MHz),也可以将HSI作为PLL的输入,但此时PLL的最大输出为64MHz。LSE存在时,可以将LSE作为RTC时钟,也可以将LSI作为RTC时钟,看门狗的时钟只能是LSI(40KHz左右)。
0 B* W0 h9 ^9 E下面是STM32F10x系统主时钟及总线时钟配置流程:
( L3 _) M* L4 ^& `7 _/ Z( t
6 \4 c# l, P' w: E: \: Q' @7 w1 p) S8 I
TKY9]30$(OE40S(7([JIRBE.png

, m; I+ g, q/ W) A: W1 V: r: M. u3 C, e
2 [- N( G7 @* _) ]/ Z1.任意时钟倍频或者分频系数必须在该时钟未使能之前修改,例如PLL倍频系数,当PLL时钟使能后,该倍频系数数被锁定,无法修改,必须先失能PLL,再修改参数,其他时钟亦是如此。/ \6 f9 a# B4 l+ \* W  \' d
5 E' S( @: |, J1 Y5 A
2.PLL时钟、RTC时钟、系统时钟源切换时,只有当目标时钟就绪时才会切换,否则无法切换。一旦某个时钟源被确定,除非复位,该时钟源不会被停止
8 y5 O; V4 k; Y# G5 @9 ?% x* L" M! M4 U( H" U  @5 [  g
现根据上述流程,一步一步的进行时钟配置:
1 Z# N  e# `- f% b尽管时钟树如此复杂,但实际上也就需要配置以下两个寄存器即可!: U5 u, s4 K) s, F: G

- R; r3 m4 J1 b1 m- B3 N* _
9QOT@@1GNOR)TQDH9DSC{_3.png

( y, i" ?  R! x+ ]8 ], ]( @9 S4 x) ?1 k, J8 J& x

! f, o5 D4 @* T/ w
)F$VH~58H8C{`NFQB_N_E`S.png
/ l0 z3 r) W6 F, c+ f
- u1 j7 `; y' U4 G6 @. D% g+ t
HSE配置(如HSE不存在则时钟错误)
9 |% T! o9 g8 u6 d
  1. RCC->CR |= (1<<16);//使能HSE
    - A- Q& a/ B/ D% g' T& H
  2. while((RCC->CR & (1 << 17))==0);//等待HSE就绪
    $ U9 V% T3 l- p( W% A
  3. RCC->CR |= (1<<19);//如果外部 8-24MHz振荡器就绪,时钟监测器开启。0 C+ S% i& L7 n& g' C2 b

  4.   g9 L. i* U  Z+ k$ E
  5. //下面是HSI配置 若有需要可以加上
    ' w7 Q' N1 U- m7 t7 z! B
  6. RCC->CR |= (0x01);//使能HSI8 J$ O2 x, T+ b+ N+ n  H6 C
  7. while((RCC->CR & 0x02)==0);//等待HSI就绪
复制代码
# ^: E  c" M* E- T2 g& |
FLASH访问配置
  ]1 o1 }: u% O& T* P3 y, o
  1. FLASH->ACR | = 0x10;//FLASH启用预取缓冲区/ n+ G7 B9 o2 A) n% I
  2. FLASH->ACR & = 0x03;//清0低2位
    / f7 Y) |7 g  n; e; {( d
  3. FLASH->ACR |=0x02;//等待2个周期
复制代码

& H7 C8 W7 ^2 C9 T  L9 b9 OAHB、APB时钟分频系数配置
0 W. h8 o7 L  x4 F( \
  1. RCC->CFGR = ((0 & 0xf) << 4)|(RCC->CFGR & ~(0xf << 4));//AHB不分频 72M 9 W/ b8 Y5 T# ]/ x/ g8 S
  2. RCC->CFGR = ((4 & 0x7) << 8)|(RCC->CFGR & ~(0x7 << 8));//APB1 二分频 36M
    6 y. U" G. ^8 D) d' @7 K0 u5 m* z" `
  3. RCC->CFGR = ((0 & 0x7) << 11)|(RCC->CFGR & ~(0x7 << 11));//APB2 不分频  72M
复制代码
: k, l' i& O( ~* H. V
PLL配置% S# m5 q1 {2 G9 h2 f" Y) U
  1. RCC->CFGR = ((7 & 0xf) << 18)|(RCC->CFGR & ~(0xf << 18));//PLL输出9倍频  8M*9=72M
    / S# `4 s+ D, N2 Y! T1 ]
  2. RCC->CFGR = ((1 & 0x01) << 16)|(RCC->CFGR & ~(0x01 << 16));//PLL时钟源选择HSE
    7 n0 b3 s1 A7 N0 Q- T
  3. RCC->CFGR = ((0 & 0x01) << 17)|(RCC->CFGR & ~(0x01 << 17));//HSE不分频接入PLL: e6 i3 s9 P$ S  U0 x5 ]! d
  4. RCC->CR |= (1<<24);//使能PLL
    " E! j! d- N; ]5 C5 w* y5 |9 c
  5. while((RCC->CR & (1 << 25))==0);//等待PLL就绪
复制代码
1 N5 _! ]* @6 N* S& e6 f/ I
系统时钟配置
" D- j, h  K* l6 y; s) ?+ i2 ?/ `
  1. RCC->CFGR = (0x02 & 0x03)|(RCC->CFGR & ~(0x03));//系统时钟源选择PLL
    : n2 N3 c4 H1 B6 n- c/ W: T( i( |
  2. while((RCC->CFGR & 0x0c)!=0x08);//等待PLL作为系统时钟源就绪
复制代码

, t$ p7 j0 E7 _7 c' x$ t$ C$ G: h这样系统时钟就配置完成了,如果HSE接的是8MHz晶振,那么SYSCLK=AHB=APB2=72MHz,APB1=36MHz 。这里并没有开启RTC、USB等时钟,大家可以根据需要自行开启。
% A3 s) m2 U) Z% R7 C. U# i对系统时钟的初始化,在STM32F10x的库函数system_stm32f10x.c文件中:SystemInit函数也有类似的实现方法,大家也可以参考下。6 P2 c0 w1 U/ A' J7 M" s

+ i$ i, [" {" O1 A四、备注  E! G' z. G, ?3 h. C0 ^
系统复位后,HSI 振荡器被选为系统时钟。
7 d% K5 f& l$ J0 u( |7 r; _4 I. B: f' Y+ ]1 q; R
时钟安全系统可以通过软件被激活。一旦其被激活,时钟监测器将在 HSE 振荡器启动延迟后被使能,并在 HSE 时钟关闭后关闭。如果 HSE 时钟发生故障,此振荡器自动地被关闭,时钟失效事件将被送到高级定时器 TIM1 的断路输入端,并产生时钟安全中断 CSSI,允许软件完成营救操作。此 CSSI 中断被连接到 Cortex-M3 NMI 的中断。1 G! b0 C1 F0 D0 L6 p
: Y, I1 H" Y) g) w9 I/ a
如果独立看门狗已经由硬件选项或软件启动,LSI 振荡器将被强制在打开状态,并且不能被关闭。在 LSI 振荡器稳定后,时钟供应给 IWDG。
) b* m6 I% J! ~( A7 k/ p, N9 s$ f. H; H
FLASH预取缓冲器:) a2 A" \) m; y. F4 ~
* F2 B. V1 n* g: v. J
复位后预取缓冲器处于开启状态
0 \8 \3 R5 E) i: F' r! B. R. j& W! h4 ]% U4 C
只有当SYSCLK低于24MHz时才能转换预取缓冲器的开启/关闭状态。通常在系统的初始化程序中开启或关闭预取缓冲器,此时微控制器运行于内部的8MHz阻容振荡器(HSI)。
, K8 V6 Z+ K7 r: h$ |5 u! D# ^, C; K" S3 l
注意:当 AHB 时钟的预分频系数不为 ’1’ 时,必须打开预取缓冲器 (FLASH_ACR[4]=1) 。如果在系统中没有高频率的时钟,即HCLK频率较低时,闪存的访问只需半个HCLK周期(半周期的闪存访问只能在时钟频率低于8MHz时进行,使用HSI或HSE并且关闭PLL时可得到这样的频率);在闪存访问控制寄存器中有一个控制位(FLASH_ACR[3])可以选择这种工作方式。
2 l& c* H6 {& e
8 u4 W1 g% ~# R- P' u# z5 @注意:当使用了预取缓冲器和 AHB 时钟的预分频系数不为 ’1’ 时,不能使用半周期访问方式。
+ }, O& a2 o+ C$ k# Q$ z0 p7 u. r" x  ], s

2 Q! X! l* ]% v$ J  U/ y4 p4 h, J& Y6 Q& T
_T]8Z)V%2VIEX0BYS2831MD.png
PIAPW74SGTJHC43G4%2L$VY.png
收藏 评论0 发布时间:2021-11-30 22:16

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版