OpenMCU(五):STM32F103时钟树初始化分析

概述

        本文主要描述了STM32F103初始化过程系统时钟的初始化,主要描述了系统时钟的初始化,AHB总线时钟,APB总线时钟等的初始化。

硬件板卡3d图

时钟树

STM32F103的时钟树,如下所示:

时钟源选择

从STM32F103的时钟树框图,我们可以看到:

1、有可选的1路高速外部时钟接口,作为系统时钟的时钟源;

2、1路32.768的可选低速时钟,作为系统RTC和watchdog的时钟源;

3、1路内部的可选8M 高速时钟,作为系统时钟的时钟源;

系统时钟选择

根据时钟树所示,可选的系统的时钟选择,如下所示:

1、内部8M的HSI直接作为系统的时钟源,如果使用HSI作为系统时钟源的话,最大SYSCLK只能输出到64MHz;

2、HSI或者HSE的通过PLL的倍频后,作为系统时钟源;

3、HSE的输出,直接作为系统的时钟源;

通过系统时钟源的来源描述,系统的时钟源可以根据硬件板卡的制作情况,进行选择;作者自己设计的PCB板子上,因为没有连接外部晶振,因此将HSI作为系统的时钟源选择。后续的时钟初始化代码分析,会讲解怎么将HSI设置为系统的时钟源;

其他外设时钟

根据STM32F103的时钟树,其他外设控制器的时钟的来源如下所示:

1、USB控制器的时钟,直接来源于PLLCLK,然后经过USB预分频,最终达到48M的时钟输出,作为USB控制器的时钟;

2、I2S音频控制器的时钟,直接来源于SYSCLK, 和SYSCLK的时钟相同;

3、SDIO, FSMC, HCLK 等时钟,直接来自于AHB总线的时钟输出;

4、剩余外设的时钟自于APB1或者APB2,这里不再这里详细描述;

时钟初始化设置

由于作者自己设计的硬件板子,使用了内部的8M作为整个CPU的时钟源,因此,下面以使用内部8M的高速时钟的情况,进行源码讲解,设置源码如下所示:

void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef clkinitstruct = {0};
  RCC_OscInitTypeDef oscinitstruct = {0};

  /* Configure PLL ------------------------------------------------------*/
  /* PLL configuration: PLLCLK = (HSI / 2) * PLLMUL = (8 / 2) * 16 = 64 MHz */
  /* PREDIV1 configuration: PREDIV1CLK = PLLCLK / HSEPredivValue = 64 / 1 = 64 MHz */
  /* Enable HSI and activate PLL with HSi_DIV2 as source */
  oscinitstruct.OscillatorType  = RCC_OSCILLATORTYPE_HSI;     /* HSI作为系统时钟源 */
  oscinitstruct.HSEState        = RCC_HSE_OFF;                /* 关闭HSE时钟 */
  oscinitstruct.LSEState        = RCC_LSE_OFF;                /* 关闭LSE时钟 */
  oscinitstruct.HSIState        = RCC_HSI_ON;                 /* 开启HSI时钟 */
  oscinitstruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  oscinitstruct.HSEPredivValue    = RCC_HSE_PREDIV_DIV1;
  oscinitstruct.PLL.PLLState    = RCC_PLL_ON;
  oscinitstruct.PLL.PLLSource   = RCC_PLLSOURCE_HSI_DIV2;
  oscinitstruct.PLL.PLLMUL      = RCC_PLL_MUL16;
  if (HAL_RCC_OscConfig(&oscinitstruct)!= HAL_OK)
  {
    /* Initialization Error */
    while(1);
  }

  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
     clocks dividers 将PLL的输出,作为系统时钟*/
  clkinitstruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  clkinitstruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  clkinitstruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  clkinitstruct.APB2CLKDivider = RCC_HCLK_DIV1;
  clkinitstruct.APB1CLKDivider = RCC_HCLK_DIV2;
  if (HAL_RCC_ClockConfig(&clkinitstruct, FLASH_LATENCY_2)!= HAL_OK)
  {
    /* Initialization Error */
    while(1);
  }
}

        由于作者为了减少PCB板子的尺寸,因此在设计过程中,硬件上没有接外部晶振和32.768的低速晶振。因此只能使用内部HSI作为时钟源,但是在使用HSI作为时钟源时,系统的时钟最大只能设置到64MHz;

代码主要逻辑如下:

1、将HSI的晶振作为系统的晶振输入;

2、关闭HSE时钟源;

3、关闭LSE时钟源;

4、计算出SYSCLK = HSI /2 * PLL_MUl16 = 8/2 * 16 = 64M;

5、调用HAL_RCC_OscConfig()接口,设置系统时钟源;

6、选择PLLCLK的输出,最为系统时钟(64M);

总结

        本文主要描述了,在STM32F103 CPU初始化过程中,系统时钟的初始化。虽然,我们可以利用ST提供的上位机图形化工具进行时钟配置,简单的勾选就可以产生我们需要的代码。但是,作为一个嵌入式开发程序员,我觉得,还是有必要去分析源码,了解CPU的内部原理和HAL层代码,这样才能根据自己产品的实际需求情况,设计出更具有性价比的产品。

链接

yanl1229/STM32F103

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值