前言
学习以及使用STM32F103有一段时间了,平时虽然会使用一些库函数,但是对于很多东西任然一知半解,所以趁着假期再对最重要的时钟部分进行详细学习。果然印证了一些知识,将零碎的知识又串起来了。
系统时钟框图
如果想要彻底了解STM32F10x的时钟到底怎么回事,手绘一张系统时钟框图是最好的选择。下图是根据正点原子的框图,自己手绘了半天的改编版(这篇主要就是图,收图给点鼓励的赞)。
图解
- 首先,5个绿色的部分是STM32的时钟源,系统时钟、所有的外设时钟都来自于这五个时钟源。黄色的是分频器。
- HSI(High Speed Internal Clock Signal)即内部高速时钟信号,时钟频率约等于8MHz,因为RC振荡器产生的频率是不够稳定的。它可以直接通过选择器③到系统时钟。也可以2分频后作为选择器②的输入,再倍频给系统时钟。
- HSE(High Speed External Clock Signal)即外部高速时钟信号,外接晶振的范围4-16M。一般来说会外接一个8M的晶振。它可以直接作为选择器①的输入,或者2分频后作为选择器①的输入。还可以作为系统时钟的时钟源,也就是选择器③的输入。
- 我们经常会使用HSE外部晶振时钟作为PLL的输入,最终产生系统时钟。如果外部晶振突然坏了,会导致系统时钟崩溃。这时候,CSS时钟监控系统,一旦检测到HSE外部时钟信号丢失,可以自动切换SYSCLK=HSI,也就是自动切换内部时钟信号。
- LSE(Low Speed External Clock signal)即外部低速时钟信号,一般会外接32.768KHz的晶振,它的作用是提供频率给RTC(内部实时时钟)。另外RTC的时钟来源还可以是HSE(外部高速时钟)的128分频。
- LSI(Low Speed Internal Clock Signal)即内部低速时钟信号。由内部的RC振荡器产生,频率约等于40KHz。一般来说LSI作为独立看门狗的时钟。也可以是RTC的时钟源。
- MCO(Microcontroller clock output)即微控制器时钟输出,也就是输出内部时钟,引脚是PA8。它的来源有4个,可以是系统时钟、外部高速时钟、内部高速时钟、PLL倍频器时钟的2分频。注意:1.该时钟输出,在启动和切换MCO时钟源时可能会被截断。2.在系统时钟作为输出源时,输出时钟频率不超过50MHz(IO口最高频率)。
- USB时钟,一般情况是48MHz,来源PLLCLK倍频器时钟经过USB分频器,USB分频器可以分频1倍或者1.5倍,因为USB时钟频率一般是48MHz,分频系数只有1和1.5,所有PLLCLK倍频器时钟的频率一般设为48MHz或者72MHz。
- AHB分频器,总线分频器,分频系数一共有9种,我们一般设置系统时钟SYSCLK是72MHz,AHB分频系数设为1,这时HCLK的频率为72MHz。
AHB分频器可以经过APB1分频器,通过APB1的分频,产生PCLK1的时钟。PCLK1时钟,可以挂一些低速的外设,比如通用定时器。
AHB分频器可以经过APB2分频器,通过APB2的分频,产生PCLK2的时钟。PCLK2时钟,可以挂一些高速的外设,比如定时器1。 - APB分频器,分频因子共有5种,1、2、4、8、16。下面挂载很多外设,在使用任何外设之前,都要使能相应的时钟。如果不使用外设,还打开APB分频器,就比较耗电。
库函数配置
在stm32f10x_rcc.h文件中,声明了操作RCC相关寄存器的函数。以下是部分截图示例:
可以将RCC寄存器函数主要分为7类,如图所示:
寄存器配置
寄存器地址名称映射文件stm32f10x.h中
/**
* @brief Reset and Clock Control
* 复位和时钟控制
*/
typedef struct
{
__IO uint32_t CR; //HSI、HSE、CSS、PLL等的使能和就绪标志位
__IO uint32_t CFGR; //PLL等的时钟源选择,分频系数的设定
__IO uint32_t CIR; //清除/使能 时钟就绪中断
__IO uint32_t APB2RSTR; //APB2线上外设复位寄存器
__IO uint32_t APB1RSTR; //APB1线上外设复位寄存器
__IO uint32_t AHBENR; //DMA,SDIO等时钟复位
__IO uint32_t APB2ENR; //APB2线上外设时钟使能
__IO uint32_t APB1ENR; //APB1线上外设时钟使能
__IO uint32_t BDCR; //备份域控制寄存器
__IO uint32_t CSR; //控制状态寄存器
#ifdef STM32F10X_CL
__IO uint32_t AHBRSTR;
__IO uint32_t CFGR2;
#endif /* STM32F10X_CL */
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
uint32_t RESERVED0;
__IO uint32_t CFGR2;
#endif /* STM32F10X_LD_VL || STM32F10X_MD_VL || STM32F10X_HD_VL */
} RCC_TypeDef;
STM32参考手册一些操作
使用时可查阅参考手册文档
更详细的寄存器操作可以,查看参考手册,这里仅做示例。