1、STM32配置系统时钟的步骤
1、系统时钟配置步骤
先配置系统时钟,后面的总线才能使用时钟频率
2、外设时钟使能和失能
STM32为了低功耗,一开始是关闭了所有的外设的时钟,所以外设想要工作,首先就要打开时钟,所以后面在使用外设的时候必须先用这个宏打开相应的时钟,比如打开GPIOA、ADC等外设的时钟
3、sys_stm32_clock_init 函数(F1)
系统时钟初始化函数
2、系统时钟配置步骤

3、外设时钟使能和失能

4、sys_stm32_clock_init 函数(F1)

c
HAL_RCC_OscConfig() //选择时钟源、配置PLL
HAL_RCC_ClockConfig() //选择系统时钟源,配置总线分频器
//主要使用这两个HAL库函数实现系统时钟配置
1、HAL_RCC_OscConfig()函数
c
HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)
参数含义
c
typedef struct
{
uint32_t OscillatorType; /* 选择需要配置的振荡器,比如选择HSE高速外部时钟 */
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;
PLL配置结构体
c
typedef struct
{
uint32_t PLLState; /* PLL 状态 */
uint32_t PLLSource; /* PLL 时钟源 */
uint32_t PLLMUL; /* PLL 倍频系数 2-16倍频 */
}RCC_PLLInitTypeDef;
2、HAL_RCC_ClockConfig函数(F1)
c
HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency)
c
typedef struct
{
uint32_t ClockType; /* 要配置的时钟(SYSCLK/HCLK/PCLK1/PCLK2) */
uint32_t SYSCLKSource; /* 系统时钟源 */
uint32_t AHBCLKDivider; /* AHB 时钟预分频系数 */
uint32_t APB1CLKDivider; /* APB1 时钟预分频系数 */
uint32_t APB2CLKDivider; /* APB2 时钟预分频系数 */
}RCC_ClkInitTypeDef;
c
uint32_t FLatency
#define FLASH_LATENCY_0 0x00000000U /* FLASH 0个等待周期 */
#define FLASH_LATENCY_1 FLASH_ACR_LATENCY_0 /* FLASH 1个等待周期 */
#define FLASH_LATENCY_2 FLASH_ACR_LATENCY_1 /* FLASH 2个等待周期 */
实际设置FLASH_ACR寄存器LATENCY位域,请参考《 STM32F10xxx闪存编程参考手册.pdf 》3.1小节
程序举例
1、先配置HSE_VALUE,先告诉HAL库实际高速外部晶振是多少MHz的
可以看到HSE_VALUE 8000000U
其实就是8MHz,就是在HAL库中写明了8MHz的外部晶振频率
2、在启动文件.s中,在复位函数Reset_Handler
部分调用SystemInit
函数
3、调用HAL库函数正式设置时钟
c
/**
* @brief 系统时钟初始化函数
* @param plln: PLL倍频系数(PLL倍频), 取值范围: 2~16
中断向量表位置在启动时已经在SystemInit()中初始化
* @retval 无
*/
void sys_stm32_clock_init(uint32_t plln)
{
HAL_StatusTypeDef ret = HAL_ERROR;
RCC_OscInitTypeDef rcc_osc_init = {0};
RCC_ClkInitTypeDef rcc_clk_init = {0};
rcc_osc_init.OscillatorType = RCC_OSCILLATORTYPE_HSE; /* 选择要配置HSE,也就是选择高速外部时钟振荡器 */
rcc_osc_init.HSEState = RCC_HSE_ON; /* 打开HSE */
rcc_osc_init.HSEPredivValue = RCC_HSE_PREDIV_DIV1; /* HSE预分频系数 */
rcc_osc_init.PLL.PLLState = RCC_PLL_ON; /* 打开PLL */
rcc_osc_init.PLL.PLLSource = RCC_PLLSOURCE_HSE; /* PLL时钟源选择HSE */
rcc_osc_init.PLL.PLLMUL = plln; /* PLL倍频系数 */
ret = HAL_RCC_OscConfig(&rcc_osc_init); /* 初始化 */
if (ret != HAL_OK)
{
while (1); /* 时钟初始化失败,之后的程序将可能无法正常执行,可以在这里加入自己的处理 */
}
/* 选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2*/
rcc_clk_init.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
rcc_clk_init.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; /* 设置系统时钟来自PLL */
rcc_clk_init.AHBCLKDivider = RCC_SYSCLK_DIV1; /* AHB分频系数为1 */
rcc_clk_init.APB1CLKDivider = RCC_HCLK_DIV2; /* APB1分频系数为2 */
rcc_clk_init.APB2CLKDivider = RCC_HCLK_DIV1; /* APB2分频系数为1 */
ret = HAL_RCC_ClockConfig(&rcc_clk_init, FLASH_LATENCY_2); /* 同时设置FLASH延时周期为2WS,也就是3个CPU周期。 */
if (ret != HAL_OK)
{
while (1); /* 时钟初始化失败,之后的程序将可能无法正常执行,可以在这里加入自己的处理 */
}
}