实际上,对于STM32F10x系列的芯片,如果使用库函数方式开发,芯片的时钟初始化函数已经写好,并且在启动文件(例如startup_stm32f10x_hd.s)中被自动调用,在进入main函数之前,系统以及外设时钟均配置完成,main程序中不需要对时钟再进行任何配置,直接编写应用程序即可。但是作为一个底层驱动玩家必须要打破砂锅问到底,看看STM32F10x系列芯片的时钟系统到底是怎么样的以及如何配置时钟,下文将着重分析STM32F10x的时钟系统以及用寄存器方式从零开始一步一步配置时钟。$ V2 q7 A+ F& U P 0 _6 i8 M0 v u 一、开发环境4 ~+ V: e" J2 k MDK版本:V5.28 单片机:STM32F103RCT6 Y \/ L* x; I 二、时钟树剖析 8 J7 S% G( @ c% u# o 上图就是STM32F10x的时钟树,看着十分复杂,或许有人会问,为什么STM32要把时钟设计的这么复杂?这是因为STM32的外设很多,而且不同的外设需要的时钟是不一样的,例如USB时钟一般需要48MHz,RTC时钟一般是32.768K,APB2总线上的外设最大不超过72MHz,APB1总线外设最大不超过36MHz,如何同时满足这些时钟要求呢?显然如果只设计一种时钟是不可以的,于是就有了上图中复杂的时钟系统。下面我们就来分析下上图的时钟系统。 首先可以把上图的时钟树划分为以下几个部分:. ~2 i& z2 s& \( m5 D( S# L$ w % M { G# p4 s y& q( a % d3 \- G" @0 M0 Z+ d 基础时钟介绍: 7 c: n! c7 G/ L3 [) h7 b2 q 基础时钟并不是官方提出的概念,是我个人的习惯叫法,它主要指的是HSE、LSE、HSI、LSI这四种时钟源,其主要作用如上图所示。/ c3 B7 M* y" |; y 2 h. k) k z5 U7 a7 u! J# [ 系统时钟的产生:( w9 u- E* w& D1 R 系统时钟的产生有三种方式:1>HSI内部高速时钟,一般为8MHz。 2>HSE外部高速时钟,一般为8MHz晶振。 3>PLL电路,输出频率可任意配置。其中HSI和HSE都属于基础时钟,如果使用PLL时钟作为系统时钟,PLL电路的基准输入必须是HSE或者HSI。 如果直接使用基础时钟作为系统时钟,那么系统时钟最大频率≤HSE/HSI 如果使用PLL输出时钟作为系统时钟,那么系统时钟最大频率≤72MHz 下面就以定时器为例说明上述各个时钟之间的供需关系:# U2 y r- H! s! M, U1 [$ n 如果需要使用定时器,那么首先需要开启定时器的时钟,而定时器属于外设,因此需要系统时钟提供时钟给这个外设,对于系统时钟,有两种方式提供,一种是由基础时钟(内部或外部基础时钟源)直接提供,缺点是无法产生更高的频率,时钟源是多高的频率,系统时钟最大不会超过这个频率;第二种是由PLL电路提供,优点是能够产生各种高频稳定的时钟频率,但是也需要基础时钟提供基准信号,且一般情况下STM32F10x系列PLL输出最大不超过72MHz。9 o! r; g0 a& K+ r# g 一般来说除RTC外所有的外设时钟(TIM、GPIO、DMA、USART、USB等等)必须由系统时钟提供,但某些特殊外设需要另当别论(以太网、I2S设备等)! d) u3 v. v: L( _8 w 8 j f! f5 J2 X- N% s, V 在STM32时钟树中,还有很多的分频器和倍频器,通过这些分频和倍频器就能产生各种需要的频率,但是只有PLL电路才可以倍频,即产生高于输入频率的频率,例如将8MHz的HSE作为PLL基准输入,最高可以9倍频,产生72MHz的输出频率提供给系统时钟;其余的电路只能进行分频,如TIM、USART等这些外设时钟都是通过系统时钟分频而来,所以它们的最大频率不会超过系统主时钟。 0 w+ R5 r' W4 M* Y/ }& ^ 三、时钟配置流程! x; `+ x3 q5 B' W6 K STM32F10x时钟的配置有很多种方式,如果HSE存在,那么可以使用HSE作为PLL输入,也可以不使用,还可以将HSE 128分频作为RTC时钟;当HSE不存在时,可以直接把HSI作为系统主时钟(8MHz),也可以将HSI作为PLL的输入,但此时PLL的最大输出为64MHz。LSE存在时,可以将LSE作为RTC时钟,也可以将LSI作为RTC时钟,看门狗的时钟只能是LSI(40KHz左右)。 下面是STM32F10x系统主时钟及总线时钟配置流程:* s$ T' E& B2 Y$ j2 e" s6 T. Q0 Q 1.任意时钟倍频或者分频系数必须在该时钟未使能之前修改,例如PLL倍频系数,当PLL时钟使能后,该倍频系数数被锁定,无法修改,必须先失能PLL,再修改参数,其他时钟亦是如此。 6 X% C' Z& h. _8 e9 B 2.PLL时钟、RTC时钟、系统时钟源切换时,只有当目标时钟就绪时才会切换,否则无法切换。一旦某个时钟源被确定,除非复位,该时钟源不会被停止 % h5 u1 r5 J; x0 Q& O+ I 现根据上述流程,一步一步的进行时钟配置:) D T; F1 h( ]% y( J 尽管时钟树如此复杂,但实际上也就需要配置以下两个寄存器即可! - ?; q6 \7 b8 w; w$ a " a' B3 E$ [1 f; @4 Z- @ HSE配置(如HSE不存在则时钟错误)* w1 _7 D8 u; `8 \4 A
FLASH访问配置: T5 n5 ?7 O8 A8 S1 A
AHB、APB时钟分频系数配置% m( O! H5 E. z' l) z3 f
PLL配置6 A4 i9 w" b# T, Q& N
系统时钟配置$ J7 ]6 H8 W8 E K
这样系统时钟就配置完成了,如果HSE接的是8MHz晶振,那么SYSCLK=AHB=APB2=72MHz,APB1=36MHz 。这里并没有开启RTC、USB等时钟,大家可以根据需要自行开启。+ C2 O% U3 ]- M) l; K; a- Q 对系统时钟的初始化,在STM32F10x的库函数system_stm32f10x.c文件中:SystemInit函数也有类似的实现方法,大家也可以参考下。 四、备注 系统复位后,HSI 振荡器被选为系统时钟。* U ^5 m2 g+ V9 T/ |9 J% c % {* l& S7 _' v% {8 W 时钟安全系统可以通过软件被激活。一旦其被激活,时钟监测器将在 HSE 振荡器启动延迟后被使能,并在 HSE 时钟关闭后关闭。如果 HSE 时钟发生故障,此振荡器自动地被关闭,时钟失效事件将被送到高级定时器 TIM1 的断路输入端,并产生时钟安全中断 CSSI,允许软件完成营救操作。此 CSSI 中断被连接到 Cortex-M3 NMI 的中断。( @+ q$ l) _" I) v3 W 如果独立看门狗已经由硬件选项或软件启动,LSI 振荡器将被强制在打开状态,并且不能被关闭。在 LSI 振荡器稳定后,时钟供应给 IWDG。- y0 k6 O: G; {+ J, ^+ }0 T FLASH预取缓冲器: ( b4 a" Y, j4 M! }# h' k/ d 复位后预取缓冲器处于开启状态 ' @4 |6 s( K+ a 只有当SYSCLK低于24MHz时才能转换预取缓冲器的开启/关闭状态。通常在系统的初始化程序中开启或关闭预取缓冲器,此时微控制器运行于内部的8MHz阻容振荡器(HSI)。 注意:当 AHB 时钟的预分频系数不为 ’1’ 时,必须打开预取缓冲器 (FLASH_ACR[4]=1) 。如果在系统中没有高频率的时钟,即HCLK频率较低时,闪存的访问只需半个HCLK周期(半周期的闪存访问只能在时钟频率低于8MHz时进行,使用HSI或HSE并且关闭PLL时可得到这样的频率);在闪存访问控制寄存器中有一个控制位(FLASH_ACR[3])可以选择这种工作方式。 7 @0 E& H9 f' v9 l 注意:当使用了预取缓冲器和 AHB 时钟的预分频系数不为 ’1’ 时,不能使用半周期访问方式。 ! J* Z: c* {/ X) q! h# G& t# A |
STM32F103移植LittlevGUI代码
【MCU实战经验】+自制MP3使用STM32F103ZET6和ch375读取u盘,vs1003解码,音质超棒
串口通信波特率异常的解决办法
小马哥STM32F103开源小四轴RoboFly全部资料大放送
【MCU实战经验】+STM32F103的uCOSII详细移植
游名科技:STM32F103+TMC2160:86步进电机和驱动一体原理图/PCB...
在高容量 STM32F103xx 微控制器中实现 ADPCM 算法
STM32F103标准库开发---SPI实验---读写 W25Q128 外部 Flash
RT-Thread在STM32F103RC上移植
STM32固件库分享,超全系列整理