SystemInit时钟系统初始化函数剖析

331 阅读2分钟

时钟结构体定义
图片.png
RCC_CR时钟控制寄存器
RCC_CFGR时钟配置寄存器
RCC_CIR时钟中断寄存器

SystemInit函数部分代码解析(基于STM32F10X_HD系列)

打开HSI(第0位置1)

RCC->CR |= (uint32_t)0x00000001;

图片.png
初始化状态(Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits),详见STM32中文参考手册62,63

 RCC->CFGR &= (uint32_t)0xF0FF0000;

图片.png
图片.png

配置默认寄存器状态(Reset置0)

  /* Reset HSEON, CSSON and PLLON bits */
  RCC->CR &= (uint32_t)0xFEF6FFFF;

  /* Reset HSEBYP bit */
  RCC->CR &= (uint32_t)0xFFFBFFFF;

图片.png

  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
  RCC->CFGR &= (uint32_t)0xFF80FFFF;

图片.png

关掉所有中断和配置位,重置CFG2寄存器

  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x009F0000;

  /* Reset CFGR2 register */
  RCC->CFGR2 = 0x00000000;

图片.png
图片.png

调用时钟频率函数

SetSysClock();

配置时钟频率,以72MHZ为例
开启振荡器

RCC->CR |= ((uint32_t)RCC_CR_HSEON);

其中#define RCC_CR_HSEON ((uint32_t)0x00010000)
等待稳定就绪

do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

其中#define RCC_CR_HSERDY ((uint32_t)0x00020000)
设置HSE时钟状态

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

启用缓存区使能,CPU进行两个等待状态(通过闪存访问控制寄存器)

    /* 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;

其中#define FLASH_ACR_PRFTBE ((uint8_t)0x10),#define FLASH_ACR_LATENCY ((uint8_t)0x03)

图片.png
时钟源选择

图片.png

    /* HCLK = SYSCLK */ //AHB分频为1
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK */ //APB2预分频为1
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK/2 */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

图片.png
图片.png
HSE通过PLL倍频

    /*  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);

使能PLL,设置PLL为系统时钟来源

    /* 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;

具体时钟部分参考STM32中文参考手册更为详细,此处仅进行简要的概括。