问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

STM32单片机时钟系统详解:从基础概念到具体配置

创作时间:
作者:
@小白创作中心

STM32单片机时钟系统详解:从基础概念到具体配置

引用
CSDN
1.
https://m.blog.csdn.net/weixin_64192009/article/details/144961439

本文主要介绍STM32单片机的时钟系统,重点讲解了STM32F1系列的时钟树结构、相关配置函数以及系统时钟配置步骤。内容详尽,包含具体代码示例和时钟树图,适合对STM32单片机感兴趣的开发者阅读。

一、什么是时钟?

  1. 简单来说,时钟是具有周期性的脉冲信号,最常用的是占空比50%的方波。

  2. 时钟对单片机来说就像脉搏一样重要,在单片机中起着至关重要的作用。搞懂时钟走向及关系是很有必要的。

二、STM32F1

1. 时钟树图

从长竖线下来左右两边分别是芯片外部和芯片内部。

(1)两组引脚:外部时钟源

  • OSC_OUT、OSC_IN:外部高速晶振所连接的引脚
  • OSC32_OUT、OSC32_IN:外部低速晶振所连接的引脚

(2)四个时钟源

一般我们选用(8MHz)HSE作为时钟源,材料一般是石英晶体(LSE的材料一般也是石英)。

H:high L:low S:speed I:internal E:external

实物图:

时钟源优缺点:

外部:成本高、稳定性高

内部:成本低、不太稳定

(3)时钟树图说明

① 当HSI被用于作为PLL时钟的输入时,系统时钟能得到的最大频率是64MHz。

② 用户可通过多个预分频器配置AHB、高速APB(APB2)和低速APB(APB1)域的频率。AHB和 APB2域的最大频率是72MHz。APB1域的最大允许频率是36MHz。

③ SDIO接口的时钟频率固定为HCLK/2。

④ RCC(复位和时钟控制)通过AHB时钟(HCLK)8分频后作为Cortex系统定时器(SysTick)的外部时钟。通过对SysTick 控制与状态寄存器的设置,可选择上述时钟或Cortex(HCLK)时钟作为SysTick时钟。(系统嘀嗒定时器)

⑤ ADC时钟 由高速APB2时钟经2、4、6或8分频后获得。ADCCLK最大14MHz

72MHz/6=12MHz

⑥ 定时器时钟频率分配由硬件按以下2种情况自动设置:APB1和APB2线上的TIM频率都是72MHz

  • 如果相应的APB预分频系数是1,定时器的时钟频率与所在APB总线频率一致。
  • 否则,定时器的时钟频率被设为与其相连的APB总线频率的2倍。

TIM1和TIM8是高级定时器;TIM6和TIM7是基本定时器;TIM2~TIM5是通用定时器。

⑦ FCLK是Cortex™-M3的自由运行时钟。详情见ARM的Cortex™-M3技术参考手册。

⑧ 内核的:AHB总线上的外设,SDIO、FSMC、存储器和DMA

2. STM32F103时钟树简图

  • 高频部分:

如上图所示,系统时钟的来源均来自高频部分(HSE、HSI和PLL(锁相环输出)),一般我们选择PLLCLK(锁相环输出)作为系统时钟来源。

①、内核时钟来源是HCLK(AHB总线时钟,72MHz),部分外设(SDIO、DMA、FSMC、Flash等)时钟来源也来自HCLK,即挂载在AHB总线上

②、挂载在APB1、APB2上的外设的基础频率分别是36MHz和72MHz,但是外设的具体时钟频率是多少还要看:进入这个外设之前有无分频器、倍频器,进入之后,里面有无预分频器。

  • 低频部分:

LSE:是RTC实时时钟的主要来源(优选);

LSI:主要用于给独立看门狗(IWDG)和RCT提供时钟,(RC振荡器不是很精准)。

(RTC时钟来源,优选LSE,次选HSE/128分频,最后才选LSI。)

  • 其他说明:

(1)、SYSCLK官方最大为72MHz,但是可以超频(暂不考虑)。

(2)、如果选择时钟源是HSI(8M),8MHz/2*16=64MHz(最大),系统时钟是得不到72MHz的。

3. 相关函数解析

(1)HAL_RCC_OscConfig()

Osc(振荡器)

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;
// RCC_PLLInitTypeDef结构体成员
typedef struct 
{ 
    uint32_t  PLLState;     /* PLL 状态 */ 
    uint32_t  PLLSource; 	/* PLL 时钟源 */ 
    uint32_t  PLLMUL; 		/* PLL 倍频系数 */ 
}RCC_PLLInitTypeDef;  

这个函数主要就是对RCC_OscInitTypeDef这个结构体的一些配置,主要是对时钟源和锁相环的配置。

(2)HAL_RCC_ClockConfig()

HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef  *RCC_ClkInitStruct, uint32_t FLatency)
// RCC_ClkInitTypeDef结构体成员
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 				/* 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小节

我们一般用的是72MHz的主频,所以是选择两个等待状态,010:FLASH_LATENCY_2

这个函数主要是用来配置系统时钟及时钟源的选择,配置进入AHB总线、APB1、APB2时钟线前的预分频器的配置,进而配置正确的频率HCLK(72MHz)、PCLK1(36MHz)、PCLK2(72MHz)。

  • 为什么要设置FLatency参数?

Flash的时钟来源是AHB上的72MHz,但Flash本身最大均需24MHz,所以使用72MH访问Flash需要等待。

(3)__HAL_RCC_PPP_CLK_ENABLE()

PPP:代表具体的外设,如GPIOA、GPIOB、USART1、ADC、......等。

表示使能某个具体的外设时钟,这个函数对应下图的操作。

我们要使用某个外设,必需先使能该外设时钟!!!

与之对应的就是失能时钟函数:

__HAL_RCC_PPP_CLK_DISABLE(); /* 禁止 PPP 时钟 */

4. 系统时钟配置步骤

SystemInit()函数的调用说明:

在启动文件内的Reset Handle复位中断服务函数中调用

SystemInit()内只配置了总段向量所在位置,并没有配置适中相关的,所以对F103来,可不调用,而在有些系列,他可能还对单片机的时钟系统相关的寄存器进行复位(H7系列,必须调用),不同版本的库,做的事不一样。

(1)代码段

// stm32f1xx_hal_conf.h
#if !defined  (HSE_VALUE)
  #define HSE_VALUE    8000000U /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};                   // 振荡器结构体变量初始化
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};                   // 时钟结构体变量初始化
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;    // 振荡器类型为HSE
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;                      // HSE使能
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;       // HSE预分频值为1:8MHz/1=8MHz
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;                      // HSI使能
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;                  // PLL锁相环使能
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;          // PLL锁相环时钟源为HSE
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;                  // PLL锁相环倍频系数为9:8MHz*9=72MHz
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)           // 初始化振荡器配置
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks 初始化CPU、AHB和APB总线时钟
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK     // 要配置的时钟:HCLK、SYSCLK、PCLK1、PCLK2
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;                 // 系统时钟源为PLL锁相环时钟
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;                        // AHB时钟分频系数为1:72MHz/1=72MHz
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;                         // APB1时钟分频系数为2:72MHz/2=36MHz
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;                         // APB2时钟分频系数为1:72MHz/1=72MHz
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)   // 初始化时钟配置
  {
    Error_Handler();
  }
}

(2)图解

  • MCO:STM32对外部输出时钟的通道,引脚PA8的复用功能。

三、STM32F4

四、STM32F7

五、STM32H7

六、其他问题

  1. 在stm32f103单片机的时钟系统中,APB1总线最大允许是36MHz,但是APB1预分频器上却有1分频,理论上最小的预分频系数不应该是2吗?这样才可以保证APB1最大为36Mz,如果使用1分频的话,得到了72MHz了。
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号