一、STM32的时钟树
二、时钟源
对于 STM32F1,输入时钟源(InputClock)主要包括 HSI,HSE,LSI,LSE。其中,从 时钟频率 来分可以分为 高速时钟源 和 低速时钟源,其中 HSI、HSE 是高速时钟,LSI 和 LSE 是低速时钟。从 来源 可分为 外部时钟源 和 内部时钟源,外部时钟源就是从外部通过接晶振的方式获取时钟源,其中 HSE 和 LSE 是外部时钟源;其他是内部时钟源,芯片上电即可产生,不需要借助外部电路。
- 高速外部振荡器 HSE(High Speed External Clock signal)
- 外接 石英/陶瓷谐振器,频率为 4MHz~16MHz。常用的频率为 8MHz。
- 低速外部振荡器 LSE(Low Speed External Clock signal)
- 外接 32.768kHz 石英晶体,主要作用于 RTC 的时钟源。
- 高速内部振荡器 HSI(High Speed InternalClock signal)
- 由 内部RC振荡器 产生,频率为 8MHz。
- 低速内部振荡器 LSI(Low Speed Internal Clock signal)
- 由 内部RC振荡器 产生,频率为 40kHz,可作为 独立看门狗的时钟源。
芯片上电时默认由内部的 HSI 时钟启动,如果用户进行了硬件和软件的配置,芯片才会根据用户配置调试尝试切换到对应的外部时钟源;
三、锁相环PLL
锁相环是自动控制系统中常用的一个反馈电路,在 STM32 主控中,锁相环的作用主要有两个部分:输入时钟净化 和 倍频。前者是利用锁相环电路的反馈机制实现,后者我们用于使芯片在更高且频率稳定的时钟下工作。
在 STM32 中,锁相环的输出也可以作为芯片系统的时钟源。使用锁相环时只需要进行三个部分的配置。
【1】、PLL 时钟源
PLL 时钟来源 可以有两个,一个来自 HSE,另外一个是 HSI/2,具体用哪个由 时钟配置寄存器 RCC_CFGR 的 位16:PLLSRC 设置。
HSI 是内部高速的时钟信号,频率为 8M,根据温度和环境的情况频率会有漂移,一般不作为 PLL 的时钟来源。一般会选用 HSE 作为 PLL 的时钟来源。
当选用 HSE 作为 PLL 的输入时钟时,可以选择 不分频 或者 2分频,这个由 时钟配置寄存器 RCC_CFGR 的 位17:PLLXTPRE 设置。
【2】、PLL 时钟 PLLCLK
通过设置 PLL 的 倍频因子,可以对 PLL 的时钟来源进行 倍频,倍频因子可以是:2~16,具体设置成多少,由 时钟配置寄存器 RCC_CFGR 的 位21-18:PLLMUL[3:0] 设置。
要实现 72MHz 的主频率,我们通过选择 HSE 不分频作为 PLL 输入的时钟信号,即输入 8Mhz。倍频因子可选择 2-16 倍频,我们选择 9 倍频,这样可以得到时钟信号为 8*9=72MHz。
72M 是 ST 官方推荐的稳定运行时钟,如果你想超频的话,增大倍频因子即可,最高为 128M。
如果使用 HSI/2 作为 PLL 时钟源,那么可以得到最高主频 8MHz/2*16=64MHz。
四、系统时钟SYSCLK
STM32 的 系统时钟SYSCLK 为整个芯片提供了时序信号。对于相同的稳定运行的电路,时钟频率越高,指令的执行速度越快,单位时间能处理的功能越多。STM32 的系统时钟是可配置的,在 STM32F1 系列中,它可以为 HSI、PLLCLK、HSE 中的一个,通过 时钟配置寄存器 RCC_CFGR 的 位1-0:SW[1:0] 设置。
可以把主频通过 PLL 设置为 72MHz。仍使用 PLL 作为系统时钟源,如果使用 HSI/2,那么可以得到最高主频 8MHz/2*16=64MHz。
系统时钟输入选择,可选时钟信号有 外部高速时钟 HSE(8M)、内部高速时钟 HSI(8M)和 经过倍频的 PLLCLK(72M),选择 PLL CLK 作为系统时钟,此时系统时钟的频率为 72MHz。
五、总线时钟
5.1、AHB总线时钟HCLK
系统时钟 SYSCLK 经过 AHB预分频器 分频之后得到时钟叫 APB总线时钟,即 HCLK,分频因子可以是:[1,2,4,8,16,64,128,256,512],具体的由 时钟配置寄存器 RCC_CFGR 的 位7-4:HPRE[3:0] 设置。
片上大部分外设的时钟都是经过 HCLK 分频得到,至于 AHB 总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置,我们这里只需粗线条的设置好APB的时钟即可。我们这里设置为1分频,即HCLK=SYSCLK=72M。
5.2、APB1总线时钟PCLK1
APB1 总线时钟 PCLK1 由 HCLK 经过低速 APB预分频器 得到,分频因子可以是:[1,2,4,8,16],具体的由 时钟配置寄存器 RCC_CFGR 的位10-8:PRRE1[2:0] 决定。
APB1 总线时钟 PCLK1 选择的是 2分频,所以 APB1 总线时钟为 36M。由于 APB1 是低速总线时钟,所以 APB1 总线最高频率为 36MHz,片上低速的外设就挂载在该总线上,例如有看门狗定时器、定时器2/3/4/5/6/7、RTC时钟、USART2/3/4/5、SPI2(I2S2)与SPI3(I2S3)、I2C1与I2C2、CAN、USB设备和2个DAC。
5.3、APB2总线时钟PCLK2
APB2 总线时钟 PCLK2 由 HCLK 经过 高速APB2预分频器 得到,分频因子可以是:[1,2,4,8,16],具体由 时钟配置寄存器 RCC_CFGR 的位13-11:PPRE2[2:0] 决定。
APB2 总线时钟 PCLK2 选择的是 1 即 不分频,所以 APB2 总线时钟频率为 72M。与 APB2 高速总线链接的外设有 外部中断与唤醒控制、7个通用目的输入/输出口(PA、PB、PC、PD、PE、PF 和 PG)、定时器1、定时器8、SPI1、USART1、3个ADC 和 内部温度传感器。
六、其他时钟
6.1、USB时钟
USB 时钟是由 PLLCLK 经过 USB预分频器 得到,分频因子可以是:[1,1.5],具体的由 时钟配置寄存器 RCC_CFGR 的 位22:USBPRE 配置。USB的时钟最高是 48M。
STM32F103 内置全速功能的 USB外设,其串行接口引擎需要一个频率为 48MHz 的时钟源。该时钟源只能从 PLL 输出端获取,可以选择为 1.5分频 或者 1分频,也就是,当需要使用 USB模块 时,PLL 必须使能,并且时钟频率配置为 48MHz 或 72MHz。
6.2、Cortex系统时钟
Cortex 系统时钟由 HCLK 8分频 得到,等于 9M,Cortex 系统时钟用来驱动内核的系统定时器 SysTick,SysTick 一般用于操作系统的时钟节拍,也可以用做普通的定时。
6.3、ADC时钟
ADC 时钟由 PCLK2 经过 ADC预分频器 得到,分频因子可以是:[2,4,6,8],具体的由 时钟配置寄存器 RCC_CFGR 的 位15-14:ADCPRE[1:0] 决定。ADC 时钟最高只能是 14M,如果采样周期设置成最短的 1.5 个周期的话,ADC 的转换时间可以达到最短的 1us。
6.4、RTC时钟
RTC 时钟可由 HSE/128 分频得到,也可由低速外部时钟信号 LSE 提供,频率为 32.768KHz,也可由低速内部时钟信号 LSI 提供,具体选用哪个时钟由 备份域控制寄存器 RCC_BDCR 的 位9-8:RTCSEL[1:0] 配置。
6.5、独立看门狗时钟
独立看门狗的时钟由 LSI 提供,且只能是由 LSI 提供,LSI 是低速的内部时钟信号,频率为 30~60KHz 直接不等,一般取 40KHz。
七、时钟信号输出MCO
MCO 是 microcontroller clock output 的缩写,是微控制器时钟输出引脚,在 STM32 F1 系列中由 PA8 复用所得,主要作用是可以对外提供时钟,相当于一个有源晶振。MCO的时钟来源可以是:PLLCLK/2、HSI、HSE、SYSCLK,具体选哪个由 时钟配置寄存器 RCC_CFGR的 位26-24:MCO[2:0] 决定。
八、系统时钟配置
【1】、配置 HSE_VALUE
在 stm32f1xx_hal_conf.h 头文件中的宏定义 HSE_VALUE 匹配我们实际硬件的高速晶振频率(这里是8MHZ),代码中通过使用宏定义的方式来选择 HSE_VALUE 的值是 25M 或者 8M,这里我们不去定义 USE_STM3210C_EVAL 这个宏或者全局变量即可,选择定义 HSE_VALUE 的值为 8M。
/**
* @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSE is used as system clock source, directly or through the PLL).
*/
#if !defined (HSE_VALUE)
#if defined(USE_STM3210C_EVAL)
#define HSE_VALUE 25000000U /*!< Value of the External oscillator in Hz */
#else
#define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */
#endif
#endif /* HSE_VALUE */
【2】、调用 SystemInit 函数
在系统启动之后,程序会先执行 SystemInit 函数,进行系统一些初始化配置。启动代码调用 SystemInit 函数如下:
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
ST 官方提供的 SystemInit 函数的实现方式如下,定义在system_stm32f1xx.c 文件下,源码在 156 行左右。
/**
* @brief Setup the microcontroller system
* Initialize the Embedded Flash Interface, the PLL and update the
* SystemCoreClock variable.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
void SystemInit (void)
{
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#if !defined(STM32F105xC) && !defined(STM32F107xC)
RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F105xC */
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
RCC->CFGR &= (uint32_t)0xFF80FFFF;
#if defined(STM32F105xC) || defined(STM32F107xC)
/* Reset PLL2ON and PLL3ON bits */
RCC->CR &= (uint32_t)0xEBFFFFFF;
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x00FF0000;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000;
#elif defined(STM32F100xB) || defined(STM32F100xE)
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000;
#else
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000;
#endif /* STM32F105xC */
#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)
#ifdef DATA_IN_ExtSRAM
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM */
#endif
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif
}
【3】、选择时钟源,配置 PLL
通过 HAL_RCC_OscConfig() 函数设置 PLL 的时钟源。该函数的函数声明如下:
HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)
该函数只有一个形参,就是结构体 RCC_OscInitTypeDef 类型指针。RCC_OscInitTypeDef 结构体定义如下:
/**
* @brief RCC Internal/External Oscillator (HSE, HSI, LSE and LSI) configuration structure definition
*/
typedef struct
{
uint32_t OscillatorType; /*!< The oscillators to be configured.
This parameter can be a value of @ref RCC_Oscillator_Type */
#if defined(STM32F105xC) || defined(STM32F107xC)
uint32_t Prediv1Source; /*!< The Prediv1 source value.
This parameter can be a value of @ref RCCEx_Prediv1_Source */
#endif /* STM32F105xC || STM32F107xC */
uint32_t HSEState; /*!< The new state of the HSE.
This parameter can be a value of @ref RCC_HSE_Config */
uint32_t HSEPredivValue; /*!< The Prediv1 factor value (named PREDIV1 or PLLXTPRE in RM)
This parameter can be a value of @ref RCCEx_Prediv1_Factor */
uint32_t LSEState; /*!< The new state of the LSE.
This parameter can be a value of @ref RCC_LSE_Config */
uint32_t HSIState; /*!< The new state of the HSI.
This parameter can be a value of @ref RCC_HSI_Config */
uint32_t HSICalibrationValue; /*!< The HSI calibration trimming value (default is RCC_HSICALIBRATION_DEFAULT).
This parameter must be a number between Min_Data = 0x00 and Max_Data = 0x1F */
uint32_t LSIState; /*!< The new state of the LSI.
This parameter can be a value of @ref RCC_LSI_Config */
RCC_PLLInitTypeDef PLL; /*!< PLL structure parameters */
#if defined(STM32F105xC) || defined(STM32F107xC)
RCC_PLL2InitTypeDef PLL2; /*!< PLL2 structure parameters */
#endif /* STM32F105xC || STM32F107xC */
} RCC_OscInitTypeDef;
该结构体前面几个参数主要是用来选择配置的振荡器类型。比如我们要开启 HSE,那么我们会设置 OscillatorType 的值为RCC_OSCILLATORTYPE_HSE,然后设置 HSEState 的值为 RCC_HSE_ON 开启 HSE。对于其他时钟源:HIS、LSI、LSE,配置方法类似。
RCC_OscInitTypeDef 这个结构体还有一个很重要的成员变量是 PLL,它是结构体 RCC_PLLInitTypeDef 类型。它的作用是配置 PLL 相关参数。
/**
* @brief RCC PLL configuration structure definition
*/
typedef struct
{
uint32_t PLLState; /*!< PLLState: The new state of the PLL.
This parameter can be a value of @ref RCC_PLL_Config */
uint32_t PLLSource; /*!< PLLSource: PLL entry clock source.
This parameter must be a value of @ref RCC_PLL_Clock_Source */
uint32_t PLLMUL; /*!< PLLMUL: Multiplication factor for PLL VCO input clock
This parameter must be a value of @ref RCCEx_PLL_Multiplication_Factor */
} RCC_PLLInitTypeDef;
RCC_PLLInitTypeDef 结构体结构体主要用来设置 PLL 时钟源以及相关分频倍频参数。
【4】、选择系统时钟源,配置总线分频器
通过 HAL_RCC_ClockConfig() 函数设置系统时钟的时钟源。该函数的函数声明如下:
HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency)
该函数有两个形参,第一个形参 RCC_ClkInitStruct 是结构体 RCC_ClkInitTypeDef 类型指针变量,用于设置 SYSCLK 时钟源以及SYSCLK、AHB、APB1 和 APB2 的分频系数。第二个形参FLatency用于设置 FLASH 延迟。
RCC_ClkInitTypeDef 结构体的定义如下:
/**
* @brief RCC System, AHB and APB busses clock configuration structure definition
*/
typedef struct
{
uint32_t ClockType; /*!< The clock to be configured.
This parameter can be a value of @ref RCC_System_Clock_Type */
uint32_t SYSCLKSource; /*!< The clock source (SYSCLKS) used as system clock.
This parameter can be a value of @ref RCC_System_Clock_Source */
uint32_t AHBCLKDivider; /*!< The AHB clock (HCLK) divider. This clock is derived from the system clock (SYSCLK).
This parameter can be a value of @ref RCC_AHB_Clock_Source */
uint32_t APB1CLKDivider; /*!< The APB1 clock (PCLK1) divider. This clock is derived from the AHB clock (HCLK).
This parameter can be a value of @ref RCC_APB1_APB2_Clock_Source */
uint32_t APB2CLKDivider; /*!< The APB2 clock (PCLK2) divider. This clock is derived from the AHB clock (HCLK).
This parameter can be a value of @ref RCC_APB1_APB2_Clock_Source */
} RCC_ClkInitTypeDef;
第二个参数的可选值如下:
#define FLASH_ACR_HLFCYA_Pos (3U)
#define FLASH_ACR_LATENCY_0 (0x1UL << FLASH_ACR_LATENCY_Pos) /*!< 0x00000001 */
#define FLASH_ACR_LATENCY_1 (0x2UL << FLASH_ACR_LATENCY_Pos) /*!< 0x00000002 */
#define FLASH_LATENCY_0 0x00000000U /*!< FLASH Zero Latency cycle */
#define FLASH_LATENCY_1 FLASH_ACR_LATENCY_0 /*!< FLASH One Latency cycle */
#define FLASH_LATENCY_2 FLASH_ACR_LATENCY_1 /*!< FLASH Two Latency cycles */
标签:PLL,HSE,05,value,uint32,RCC,STM32F1,时钟 From: https://www.cnblogs.com/kurome/p/17575810.html我们要使用某个外设,必须先使能该外设的时钟;