STM32时钟系统
1、认识时钟树
什么是时钟?
简单来说,时钟是具有周期性的脉冲信号,最常用的是方波。
以STM32F1系列为例:
时钟源 | 频率 | 材料 | 用途 |
---|---|---|---|
高速外部振荡器(HSE) | 4~16MHz | 晶体/陶瓷 | SYSCLK/RTC |
低速外部振荡器(LSE) | 32.768KHz | 晶体/陶瓷 | RTC |
高速内部振荡器(HSI) | 8MHz | RC | SYSCLK |
低速内部振荡器(LSI) | 40KHz | RC | RTC/IWDG |
H: high
L: low
S: speed
I: internal
E: external
符号 | 作用 |
---|---|
时钟安全系统(CSS) | 如果HSE启动失败,切换到HSI,可进NMI中断 |
自由运行时钟(FCLK) | 用于采样中断和调试模块计时,休眠仍有效 |
- 时钟树简图
- CubeMX时钟树设置
- 时钟配置相关函数
时钟源、锁相环: HAL_RCC_OscConfig()
系统时钟、总线: HAL_RCC_ClockConfig()
使能外设时钟: __HAL_RCC_PPP_CLK_ENABLE()
扩展外设时钟(RTC/ADC/USB): HAL_RCCEx_PeriphCLKConfig()
2、配置系统时钟
2.1 系统时钟配置步骤
以STM32F1系列为例:
- 配置HSE_VALUE
- 告诉HAL库外部晶振频率,stm32f1xx_hal_conf.h
- 调用**SystemInit()**函数(可选)
- 在启动文件中调用,在system_stm32f1xx.c定义,配置外部存储器及断向量表地址
- HAL 库的**SystemInit()**函数并没有任何时钟相关配置,所以我们还必须编写自己的时钟配置函数
- 选择时钟源,配置PLL
- 通过**HAL_RCC_OscConfig()**函数设置
- 此函数在stm32f1xx_hal_rcc.h中声明,在stm32f1xx_hal_rcc.c中定义
- 选择系统时钟源,配置总线分频器
- 通过**HAL_RCC_ClockConfig()**函数设置
- 配置扩展外设时钟(可选)
- 通过**HAL_RCCEx_PeriphCLKConfig()**函数设置
3 + 4 (+ 5) = sys_stm32_clock_init()
2.2 外设时钟使能和失能
我们要使用某个外设,必须先使能该外设时钟
- HAL库使能某个外设时钟的方法
__HAL_RCC_GPIOA_CLK_ENABLE() /* 使能GPIOA时钟 */
- HAL库禁止某个外设 时钟的方法
__HAL_RCC_GPIOA_CLK_DISABLE() /* 禁止GPIOA时钟 */
2.3 sys_stm32_clock_init函数
以STM32F1系列为例:
-
HAL_RCC_OscConfig()
- 声明
HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct);
- 参数:结构体RCC_OscInitTypeDef类型指针
typedef struct { uint32_t OscillatorType; /* 需要选择配置的振荡器类型 */ uint32_t HSEState; /* HSE状态: 打开/关闭 */ uint32_t HSEPredivValue; /* HSE预分频值 */ uint32_t LSEState; /* LSE状态 */ uint32_t HSIState; /* HSI状态 */ uint32_t HSICalibrationValue; /* HSI校准值 */ uint32_t LSIState; /* LSI状态 */ RCC_PLLInitTypeDef PLL; /* PLL配置 */ }RCC_OscInitTypeDef;
typedef struct { uint32_t PLLState; /* PLL状态 */ uint32_t PLLSource; /* PLL时钟源 */ uint32_t PLLMUL; /* PLL倍频系数 */ }RCC_PLLInitTypeDef;
-
HAL_RCC_ClockConfig()
- 声明
HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency);
- 参数1:结构体RCC_ClkInitTypeDef类型指针
typedef struct { uint32_t ClockType; /* 要配置的时钟 */ uint32_t SYSCLKSource; /* 系统时钟源 */ uint32_t AHBCLKDivider; /* AHB 分频系数 */ uint32_t APB1CLKDivider; /* APB1 分频系数 */ uint32_t APB2CLKDivider; /* APB2 分频系数 */ }RCC_ClkInitTypeDef;
- 参数2:
uint32_t FLatency
用于设置 FLASH 延迟
#define FLASH_LATECY_0 0x00000000U /* FLASH 0个等待周期 */ #define FLASH_LATECY_1 FLASH_ACR_LATECY_0 /* FLASH 1个等待周期 */ #define FLASH_LATECY_2 FLASH_ACR_LATECY_1 /* FLASH 2个等待周期 */
因为 72MHz 的时钟比 Flash 的操作速度 24MHz 要快得多,操作速度不匹配容易导致Flash 操作失败,所以需要设置延时时间
具体可到 STMCU中文官网 下载《STM32F10xxx 闪存编程参考手册》,查看3 寄存器说明/3.1 闪存访问控制寄存器一节