STM32F103ZET6 时钟(2)—— 代码篇

基于特定的开发板上的时钟策略:


倍频/分频系数需要在使能 PLL 之前进行配置,所以需要在 Open PLL 之前将所有系统的时钟分频器系数以及PLL的倍频系数配置好。整个时钟的配置流程如下所示:

(1) 开启HSE,等待HSE稳定 
(2) 设置APB2、APB1、AHB分频系数 
(3) 设置PLL的时钟来源和PLL的倍频系数 
(4) 开启PLL,等待PLL稳定 

(5) 设置SYSCLK源为 PLL 的输出,读取时钟切换状态,确保PLLCLK被选为系统时钟


(1)  OSC_IN/OSC_OUT 上外接 8M 晶振。要使用外接晶振,上电后(默认使用 8M 的HSI),首先需要使能 HSE,位于RCC_CR寄存器的 bit16,即:

  /* Enable HSE */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);

接着需要等待外部时钟 HSE 稳定(轮询 RCC_CR寄存器的 bit17):

  /* Wait till HSE is ready and if Time out is reached exit */
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

(2)  接着配置 AHB 时钟为 SYSCLK ,即 AHB 分频系数为1,不分频,SYSCLK直接供给SDIO, FSMC, AHB BUS, FCLK并直接作用于APB1/APB2的输入端:

    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;

配置高速APB2 分频系数为1,即 SYSCLK ->AHB->APB2:

    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;

由于APB1的时钟最大频率为 36MHz,当前希望输入的SYSCLK为72MHz(最大频率),故需要配置低速 APB1 分频系数为2,即两分频:

    /* PCLK1 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

(3) 继续,配置 PLL 时钟源,以及 PLL 的倍频系数:

首先将需要配置的 bit 先清零:

    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));

接着

A. 选择HSE 时钟为 PLL 的输入 ,RCC_CFGR 的 bit16. 

B. 对HSE输入晶振频率不分频,直接供给 PLL 作为输入

C. 由于外部晶振时钟为 8M,得到 72MHz 最大时钟频率,故设置 PLL 倍频系数为 9:

   RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);

至此,分频/倍频系数基本设置完毕(未设置的部分采取系统 Reset 后的默认值)

(4)  开启 PLL 并等待稳定

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

    /* Wait till PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }

(5) 切换系统时钟源为 PLL 的输出:

    /* 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)
    {
    }

至此时钟配置完毕,本次配置是基于板载外接 8MHz 晶振进行的配置,若是板载其他的频率的晶振,只需改变 PLL 的倍频系数即可,此刻,系统运行在最大支持频率 72MHz 下。

完整的代码如下:

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);
 
  /* Wait till HSE is ready and if Time out is reached exit */
  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;
  }  

  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 */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK */
    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
  { /* If HSE fails to start-up, the application will have wrong clock 
         configuration. User can add here some code to deal with this error */
  }
}

猜你喜欢

转载自blog.csdn.net/zhoutaopower/article/details/80602567