1.认识时钟树
简单来说,时钟是具有周期性的脉冲信号,最常用的是占空比50%的方波
1.1.F1的时钟树
1.2.F4的时钟树(407为例)
1.3.F7的时钟树
1.4.H7的时钟树
2.配置系统时钟(F1为例)
2.1.系统时钟配置步骤
- 配置HSE VALUE:告诉HAL库外部晶振频率,stm32xxxx_hal_conf.h
- 调用Systemlnit()函数(可选):在启动文件中调用,在system_stm32xxxx.c定义
- 选择时钟源,配置PLL:通过HAL_RCC_OscConfig()函数设置
- 选择系统时钟源,配置总线分频器:通过HAL_RCC_ClockConfig()函数设置
- 配置扩展外设时钟(可选):通过HAL_RCCEx_PeriphCLKConfig()函数设置
【注】SystemInit 主要进行外部存储器配置和中断向量表地址配置。但是并没有用到,只是保留接口。HAL库的SystemInit 函数并没有任何时钟相关配置,所以后续的初始化步骤,我们还必须编写自己的时钟配置函数。
- HAL_RCC_OscConfig()函数重要参数
- HAL_RCC_ClockConfig()函数重要参数
第3,4,5步可由sys_stm32_clock_init() 函数完成
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); /* 时钟初始化失败,之后的程序将可能无法正常执行,可以在这里加入自己的处理 */}
}
2.2.外设时钟使能和失能
我们要使用某个外设,必需先使能该外设时钟
- HAL库使能某个外设时钟的方法,如:
__HAL_RCC_GPIOA_CLK_ENABLE(); /* 使能 GPIOA 时钟 */
- HAL库禁止某个外设时钟的方法,如:
__HAL_RCC_GPIOA_CLK_DISABLE(); /* 禁止 GPIOA 时钟 */