时钟系统
Created time: 2024年9月18日 15:01
Status: Done
类型: 理论
摘要: 谈谈F1系列时钟树的架构以及在实际工程中是如何配置的
时钟,就是具有周期性的脉冲信号,最常用的是占空比为50%的方波.
F1时钟树
F1时钟树总图
F1时钟树简图
我们先来看时钟树的源—时钟源.STM32F1有4个时钟源:
时钟源名称 | 频率 | 材料 | 用途 |
---|---|---|---|
高速外部时钟源(HSE) | 4-16MHz | 晶体/陶瓷 | SYSCLK/RTC |
低速外部时钟源(LSE) | 32.768KHz | 晶体/陶瓷 | RTC |
高速内部时钟源(HSI) | 8MHz | RC | SYSCLK |
低速外部时钟源(LSI) | 40KHz | RC | RTC/IWDG |
时钟源(振荡器),锁相环:HAL_RCC_OscConfig()`
系统时钟,总线:HAL_RCC_ClockConfig()
使能外设时钟:(宏)__HAL_RCC_PPP(表示任意外设)_CLK_ENABLE()
STM32为了低功耗,初始时外设的时钟都是关闭的,用什么外设就要用上面这个宏打开相应时钟.
扩展外设时钟()RTC/ADC/USB):HAL_RCCEx_PeriphCLKConfig()
不同系列这个函数的配置是不一样的,这一点要注意.
STM32CubeMX时钟树(F103)
配置系统时钟
系统时钟配置步骤
-
配置HSE_VALUE:告诉HAL库外部晶振频率,
stm32xxxx_hal_conf.h
这边我们使用正点原子开发板—8MHz(ST官方是25MHz)
-
调用SystemInit()函数(可选):在启动文件中调用,在
system_stm32xxxx.c
定义startup_stm32f103xe.s头文件中
在
system_stm32xxxx.c
文件中的定义没啥用,这里就不赘述. -
选择时钟源,配置PLL(锁相环):通过HAL_RCC_OscConfig()函数设置
-
选择系统时钟源,配置总线分频器:通过HAL_RCC_ClockConfig()函数设置
-
配置扩展外设时钟(可选):通过HAL_RCExPeriphCLKConfig()函数设置
其中3+4+5=sys_stm32_clock_init()
,这个函数在main.c的前半部分被调用:
比如这个跑马灯程序main函数:
按下F12(或者Fn+F12)
后查看其定义:
转到了sys.c下
主要就这俩函数:
这俩函数在后面也会讲到
外设时钟的使能和失能
我们要使用某个外设,必须先使能该外设时钟!!!
HAL库使能某个外设时钟的方法,如:
__HAL_RCC_GPIOA_CLK_ENABLE(); /*使能GPIOA时钟*/
HAL库禁止某个外设时钟的方法,如:
__HAL_RCC_GPIOA_CLK_DISABLE(); /*禁止GPIOA时钟*/
sys_stm32_clock_init函数(F1)
HAL_RCC_OscConfig()函数
HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OsxInitTypeDef *RCC_OscInitStruct)
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_PLLIintTypeDef PLL; /*PLL结构体*/
}RCC_OscInitTypeDef;
typedef struct
{
uint32_t PLLState; /*PLL状态*/
uint32_t PLLSource; /*PLL时钟源*/
uint32_t PLLMUL; /*pll倍频系数:2~16*/
}RCC_PLLIintTypeDef;
那么,在实际工程中这个函数长啥样?
sys.c中
点击F12
查看参数类型的定义:
分别看下他们的宏:
OscillatorType:
Ctrl+f搜索(find in Files):
点击这个就能找到
当然你直接点sys.c
中的RCC_OSCILLATORTYPE_HSE
也能到这里.两种方法.
其他2个类推,自己动手试试
接下来到锁相环的配置:
这仨就是配置锁相环(RCC_PLLIintTypeDef)的三个参数
倍频因子以形参传入,看眼main.c中的参数:
Stm32_Clock_Init(RCC_PLL_MUL9); //设置时钟,72M
F12
看眼RCC_PLL_MUL9
的定义:
我们这里*9
,因为外部晶振是8MHz
,倍频之后变72M
最后初始化一下,ret=HAL_RCC_OscConfig(&RCC_OscInitStructure);//初始化
就大功告成(并不)了!
HAL_RCC_ClockConfig()函数
HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct,uint32_t FLatency)
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;
uint32_t FLatency
#define FLASH_LATENCY_0 0x00000000U /*FLASH0等待周期*/
#define FLASH_LATENCY_1 FLASH_ACR_LATENCY_0 /*FLASH1等待周期*/
#define FLASH_LATENCY_2 FLASH_ACR_LATENCY_1 /*FLASH2等待周期*/
多跳F12
多看看,结合参考手册,超爽🤘
这样,STM32F1系列的时钟树就介绍完毕.有错误的话直接踢我