STM32F072从零配置工程-自定义时钟配置详解

从自己的板子STM32F407入手,参考官方的SystemInit()函数:

       核心在SetSysClock()这个函数,官方默认是采用HSE(设定为8MHz)作为PLL锁相环的输入输出168MHz的SYSCLK;

/**
  * @brief  Setup the microcontroller system
  *         Initialize the Embedded Flash Interface, the PLL and update the 
  *         SystemFrequency variable.
  * @param  None
  * @retval None
  */
void SystemInit(void)
{
  /* Reset the RCC clock configuration to the default reset state ------------*/
  /* Set HSION bit */
  RCC->CR |= (uint32_t)0x00000001;

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

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

  /* Reset PLLCFGR register */
  RCC->PLLCFGR = 0x24003010;

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

  /* Disable all interrupts */
  RCC->CIR = 0x00000000;

  /* Configure the System clock source, PLL Multiplier and Divider factors, 
     AHB/APBx prescalers and Flash settings ----------------------------------*/
  SetSysClock();

}

这里大致分析一下官方默认的SetSysClock()配置:

由于我个人采用的是STM32F407型号的芯片,因此精简一下函数;

总体思路的话:

        使能HSE;

        等待HSE初始化完毕,进行下一步设置;

        设置HCLK、PCLK1、PCLK2的分频系数;

        配置PLL,使能PLL,等待PLL初始化完毕;

        选择PLL作为SYSCLK,等待SYSCLK时钟设置完毕;

/**
  * @brief  Configures the System clock source, PLL Multiplier and Divider factors, 
  *         AHB/APBx prescalers and Flash settings
  * @Note   This function should be called only once the RCC clock configuration  
  *         is reset to the default reset state (done in SystemInit() function).   
  * @param  None
  * @retval None
  */
static void SetSysClock(void)
{
/******************************************************************************/
/*            PLL (clocked by HSE) used as System clock source                */
/******************************************************************************/
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* 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)
  {
    /* Select regulator voltage output Scale 1 mode */
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
    PWR->CR |= PWR_CR_VOS;

    /* HCLK = SYSCLK / 1*/
    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;

    /* PCLK2 = HCLK / 2*/
    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
    
    /* PCLK1 = HCLK / 4*/
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;

    /* PCLK2 = HCLK / 1*/
    RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK / 2*/
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;

    /* Configure the main PLL */
    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
                   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);

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

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

    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;

    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS;

    /* Select the main PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= RCC_CFGR_SW_PLL;

    /* Wait till the main PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
    {
    }
  }
  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 */
  }
}

在官方的基础上,直接设定HSE作为SYSCLK时钟:

       初始化HSE;

       等待HSE初始化成功后再继续;

       设置调压器电压输出级别为1以便使器件在最大频率工作;

       设置HCLK、PCLK1、PCLK2分频系数;

       设置HSE作为系统时钟;

void HSE_SetSysClock(void)
{
    __IO uint32_t HSEStartUpStatus = 0;
    
    RCC_HSEConfig(RCC_HSE_ON);
    
    HSEStartUpStatus = RCC_WaitForHSEStartUp();
    
    if(HSEStartUpStatus == SUCCESS)
    {
        RCC->APB1ENR |= RCC_APB1ENR_PWREN;
        PWR->CR |= PWR_CR_VOS;
        
        RCC_HCLKConfig(RCC_SYSCLK_Div1);
        
        RCC_PCLK2Config(RCC_HCLK_Div1);
        
        RCC_PCLK1Config(RCC_HCLK_Div1);
        
        RCC_SYSCLKConfig(RCC_SYSCLKSource_HSE);
        
        while(RCC_GetSYSCLKSource() != 0x04)
        {
        }
    }else
    {
        while(1);
    }
}

使用HSI经过PLL配置系统时钟:

       使能HSI时钟;

       获取HSI状态并等待HSI稳定;

       设置调节器电压输出级别配置为1;

       设置HCLK、PCLK1/2分频系数;

       设置PLL时钟分频系数;

       使能PLL并等待PLL稳定后配置PLL状态;

       设置PLL作为SYSCLK时钟并等待设置完成;

void HSI_SetSysClock(uint32_t m, uint32_t n, uint32_t p, uint32_t q)
{
    __IO uint32_t HSIStartUpStatus = 0;
    
    RCC_DeInit();
    
    RCC_HSICmd(ENABLE);
    
    HSIStartUpStatus = RCC->CR & RCC_CR_HSIRDY;
    
    if(HSIStartUpStatus == RCC_CR_HSIRDY)
    {
        RCC->APB1ENR |= RCC_APB1ENR_PWREN;
        PWR->CR |= PWR_CR_VOS;
        
        RCC_HCLKConfig(RCC_SYSCLK_Div1);
        
        RCC_PCLK2Config(RCC_HCLK_Div2);
        
        RCC_PCLK1Config(RCC_HCLK_Div4);
        
        RCC_PLLConfig(RCC_PLLSource_HSI, m, n, p, q);
        
        RCC_PLLCmd(ENABLE);
        
        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
        
        FLASH->ACR = FLASH_ACR_PRFTEN 
                     | FLASH_ACR_ICEN
                     | FLASH_ACR_DCEN
                     | FLASH_ACR_LATENCY_5WS;
        
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
        
        while(RCC_GetSYSCLKSource() != 0x08);
    }else
    {
        while(1);
    }
}

猜你喜欢

转载自www.cnblogs.com/lpfdezh/p/10948817.html
今日推荐