STM32F103是一款广泛应用于嵌入式系统的微控制器,目前在stm32上主流的库函数是HAL库。
大家在stm32学习HAL库上有很多人喜欢用Stm32CobeMX也就是图形化配置去配置。
这就导致有很多人没学习过其他芯片的库函数的朋友不太了解到底每个配置都是干嘛的,就知道这么配就是最高72MHz主频。
什么是时钟?
时钟就相当于人的心跳,没有心跳单片机是不会工作的,所以我们配置的stm32有很多模块化的时钟,我们用到那个片内外设就要第一步打开他们的相对应得时钟。
stm32有五个时钟源:
HSI 内部高速时钟
HSE 外部高速时钟
LSI 内部低速时钟
LSE 外部低速时钟
PLL 锁相环倍频输出(这个时钟一般作为倍频来使用,也就是原来如果是4mhz倍频2就是:4*2 = 8)
我们配置时钟源的第一个结构体就是 :RCC_OscInitTypeDef
让我们来看下此结构体的内部成员:
typedef struct{
uint32_t OscillatorType; //选择振荡电路
uint32_t HSEState; //外部高速时钟状态
uint32_t HSEPredivValue; //外部高速时钟分频值
uint32_t LSEState; // 外部低速时钟状态
uint32_t HSIState; // 内部高速时钟状态
uint32_t HSICalibrationValue; //HSI微调值
uint32_t LSIState; //内部低速时钟状态
RCC_PLLInitTypeDef PLL; //PLL相关配置结构体
}RCC_OscInitTypeDef; //配置内外部时钟源的结构体
大家应该发现除了第一个和最后一个外其余的可以分为四部分:
HSE开头的外部高速时钟源一个开关配置一个分频配置
HSI开头的内部高速时钟源一个开关配置一个分频配置
LSE开头的外部低速时钟源一个开关配置
LSI开头的内部低速时钟源一个开关配置
1.结构体的第一个成员 OscillatorType:
此配置的选项一共是五个
#define RCC_OSCILLATORTYPE_NONE 0x00000000U
#define RCC_OSCILLATORTYPE_HSE 0x00000001U
#define RCC_OSCILLATORTYPE_HSI 0x00000002U
#define RCC_OSCILLATORTYPE_LSE 0x00000004U
#define RCC_OSCILLATORTYPE_LSI 0x00000008U
分别是把外部高速时钟源RCC_OSCILLATORTYPE_HSE配置为当前程序的基时钟
又或者把内部高速时钟源RCC_OSCILLATORTYPE_HSI配置为当前程序的基时钟
又或者把外部低速时钟源RCC_OSCILLATORTYPE_LSE配置为当前程序的基时钟
又或者把内部低速时钟源RCC_OSCILLATORTYPE_LSI配置为当前程序的基时钟
又又或者选择RCC_OSCILLATORTYPE_NONE,什么都不配置
2.结构体的成员 HSEState,HSIState,LSEState,LSiState这四个兄弟:
:
大家先记住他们除了第一个都有俩个成员,大家初学就把他们都当成俩个就行哈
一个RCC_LSE_OFF 一个RCC_LSE_ON
RCC_HSI_OFF RCC_HSI_ON
RCC_LSI_OFF RCC_LSI_ON
![](https://img-blog.csdnimg.cn/4c7233a030054a04be2c8715200baa71.png)
PLLState PLL状态
PLLSource PLL输入源
PLLMUL PLL倍频值
PLLState有三个可选值
![](https://img-blog.csdnimg.cn/b14e09c3ee5e441984b15196d2239b02.png)
![](https://img-blog.csdnimg.cn/292905d496724e3d9ab746f9d708de2b.png)
![](https://img-blog.csdnimg.cn/3f0add7344894386b089abcea5ccda20.png)
ClkInitTypeDef.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
ClkInitTypeDef.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
![](https://img-blog.csdnimg.cn/307f6468443741248eb8837303d40ec7.png)
void HSIclock_init(void)
{
RCC_OscInitTypeDef rcctypedf; //配置内外部时钟源的结构体
rcctypedf.OscillatorType = RCC_OSCILLATORTYPE_HSI; //选择内部高速时钟
rcctypedf.HSIState = RCC_HSI_ON; //打开内部高速时钟
rcctypedf.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; //内部频率微调值选则默认
rcctypedf.PLL.PLLState = RCC_PLL_ON; //打开PLL
rcctypedf.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2; //HSI内部高速时钟2分频后作为PLL输入源
rcctypedf.PLL.PLLMUL = RCC_PLL_MUL16; //倍频到16倍 8/2*16 = 64
HAL_RCC_OscConfig(&rcctypedf); //根据 RCC_OscInitTypeDef 结构体参数配置时钟源
RCC_ClkInitTypeDef ClkInitTypeDef; //配置总线时钟配置结构体
/*配置的时钟有sysclk嵌入式系统的主要时钟,控制整个芯片的时序。配置此类型时钟将影响系统的运
行频率。
HCLK表示高速总线时钟类型。HCLK是由SYSCLK分频得到的时钟,用于控制总线访问和外设的时钟频率。
配置此类型时钟将影响外设的工作速度。
PCLK1和PCLK2表示外设时钟类型。这些时钟用于驱动微控制器的不同外设,例如UART、SPI、I2C等。配
置这些类型时钟将影响外设的工作速度。
*/
ClkInitTypeDef.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |
RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
ClkInitTypeDef.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //选择PLLclk作为时钟源
ClkInitTypeDef.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB不分频
ClkInitTypeDef.APB1CLKDivider = RCC_HCLK_DIV2; //APB1分频2
ClkInitTypeDef.APB2CLKDivider = RCC_HCLK_DIV1; //APB2不分频
/*HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct,
uint32_t FLatency)
第一个参数应传总线配置的结构体,第二个参数FLatency 表示闪存访问延迟
配置FLatency (可选值3个)
FLASH_LATENCY_0 0 等待周期(当 0 < SYSCLK < 24MHz)
FLASH_LATENCY_1 1 等待周期当 24MHz < SYSCLK ≤ 48MHz
FLASH_LATENCY_2 2 等待周期当 48MHz < SYSCLK ≤ 72MHz*/
HAL_RCC_ClockConfig(&ClkInitTypeDef,FLASH_LATENCY_2);
};
void HSEclock_init(void)
{
RCC_OscInitTypeDef rcctypedf; //配置内外部时钟源的结构体
rcctypedf.OscillatorType = RCC_OSCILLATORTYPE_HSE; //选择外部高速时钟
rcctypedf.HSEState = RCC_HSE_ON; //打开外部高速时钟
rcctypedf.HSEPredivValue = RCC_HSE_PREDIV_DIV1; //HSE不分频
rcctypedf.PLL.PLLState = RCC_PLL_ON; //打开PLL
rcctypedf.PLL.PLLSource = RCC_PLLSOURCE_HSE; //HSE内部高速时钟2分频后作为PLL输入源
rcctypedf.PLL.PLLMUL = RCC_PLL_MUL9; //倍频到9倍 8*9 = 72
HAL_RCC_OscConfig(&rcctypedf); //根据 RCC_OscInitTypeDef 结构体参数配置时钟源
RCC_ClkInitTypeDef ClkInitTypeDef; //配置总线时钟配置结构体
/*配置的时钟有sysclk嵌入式系统的主要时钟,控制整个芯片的时序。配置此类型时钟将影响系统的运
行频率。
HCLK表示高速总线时钟类型。HCLK是由SYSCLK分频得到的时钟,用于控制总线访问和外设的时钟频率。
配置此类型时钟将影响外设的工作速度。
PCLK1和PCLK2表示外设时钟类型。这些时钟用于驱动微控制器的不同外设,例如UART、SPI、I2C等。配
置这些类型时钟将影响外设的工作速度。
*/
ClkInitTypeDef.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |
RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
ClkInitTypeDef.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //选择PLLclk作为时钟源
ClkInitTypeDef.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB不分频
ClkInitTypeDef.APB1CLKDivider = RCC_HCLK_DIV2; //APB1分频2
ClkInitTypeDef.APB2CLKDivider = RCC_HCLK_DIV1; //APB2不分频
/*HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct,
uint32_t FLatency)
第一个参数应传总线配置的结构体,第二个参数FLatency 表示闪存访问延迟
配置FLatency (可选值3个)
FLASH_LATENCY_0 0 等待周期(当 0 < SYSCLK < 24MHz)
FLASH_LATENCY_1 1 等待周期当 24MHz < SYSCLK ≤ 48MHz
FLASH_LATENCY_2 2 等待周期当 48MHz < SYSCLK ≤ 72MHz*/
HAL_RCC_ClockConfig(&ClkInitTypeDef,FLASH_LATENCY_2);
}