STM32F103系统时钟

1. 在启动文件中, 找到进入系统配置的汇编指令. 

在main函数进入之前, 首先会进入SystemInit函数, 进行系统时钟配置.

STM32F103系统时钟_第1张图片

2. 找到SystemInit函数原型.

STM32F103系统时钟_第2张图片

 通过函数的注释可以了解到, 该函数的功能是: 启动系统, 嵌入的Flash接口, PLL, 和更新系统内核时钟的初始化. 这个函数应该只在复位后使用一次.

3. 找到函数体中的SetSysClock();

STM32F103系统时钟_第3张图片

通过注释可以看到, 这个函数用来配置系统时钟频率, 可以看到是72MHz.

4. 找到SetSysClockTo72()函数学习

精简版源码, 外加翻译如下.

/**
  * @brief  把系统时钟频率设置成72MHz,还得配置一下HCLK、PCLK2和PCLK1的分频器. 
  * @note   这个功能只能在重置后使用.
  * @param  None
  * @retval None
  */
static void SetSysClockTo72(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
  /* Enable HSE */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* 等待HSE准备好,如果超时就退出 */
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }  

  /* HSE启动成功往下执行 */
  if (HSEStatus == (uint32_t)0x01)
  {
    /* Enable Prefetch Buffer */
    FLASH->ACR |= FLASH_ACR_PRFTBE;

    /* Flash 2 wait state */
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    

    /* HCLK = SYSCLK = 72MHz */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK = 72MHz*/
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK = 36MHz*/
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

    /*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
                                        RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);

    /* Enable PLL */
    RCC->CR |= RCC_CR_PLLON;

    /* Wait till PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }
    
    /* Select PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    

    /* Wait till PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
  else
  { /* 如果HSE启动失败,应用程序就会有错乱的时钟配置啦。可以在这里加点代码来处理这个错误 */
  }
}

注意这里的PCLK1就是APB1总线时钟, PCLK2就是APB2总线时钟, HCLK就是AHB总线时钟, 参考手册所示.

STM32F103系统时钟_第4张图片

5.切换时钟源

//切换至 HSI 内部高速震荡时钟
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_HSI;

//切换至 HSE 外部高速震荡时钟
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_HSE;

//切换至 LSI 内部低速震荡时钟
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_LSI;

//切换至 LSE 外部低速震荡时钟
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_LSE;

//切换至 PLL 锁相环,可以自定义频率
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_PLL;

你可能感兴趣的:(stm32,嵌入式硬件,单片机)