光荣套造型:STM32时钟初探

来源:百度文库 编辑:偶看新闻 时间:2024/05/03 21:40:06
结合最近我做的项目,对STM32时钟配置有一些理解,记录下来,以便自己查看和理解。

 

  * @brief  Setup the microcontroller system
         Initialize the Embedded Flash Interface, the PLL and update the
         SystemCoreClock variable.
  * @note   This function should be used only after reset.
  * @param  None
  * @retval None
  */
void SystemInit (void)
{
 
 
  RCC->CR |= (uint32_t)0x00000001;//开启内部高速8M的RC震荡器

 

  RCC->CFGR &= (uint32_t)0xF8FF0000;//
  //SWS:系统时钟切换状态 00:HSI作为系统时钟即SYSCLK=HSI=8M
  //HPRE: AHB预分频因子,即AHB Prescaler     值为0xxx:SYSCLK不分频。即HCLK=SYSCLK
 // PPRE1:低速APB预分频因子(APB1 Prescaler) 0xx:HCLK不分频。即PCLK1=HCLK
  //PPRE2:高速APB预分频因子(APB2 Prescaler) 0xx:HCLK不分频。即PCLK2=HCLK
  //ADCPRE:ADC预分频 00:PCLK2 2分频后作为ADC时钟,即ADCCLK=PCLK2/2
//MCO:有无时钟输出控制位。0XX:MCO 端没有时钟输出
 
 
  RCC->CR &= (uint32_t)0xFEF6FFFF;
  //时钟控制寄存器RCC_RC=0x*E*6****; 就是说寄存器的第25位和第20位,第17位为0,其余保持不变。
//也就是PLL关闭;时钟监测器关闭;HSE振荡器关闭;

 
  RCC->CR &= (uint32_t)0xFFFBFFFF;
  //就是使HSEBYP=0;外部4-25MHz振荡器没有旁路;

 
  RCC->CFGR &= (uint32_t)0xFF80FFFF;
  //RCC_CFGR的第23、22、21、 20、 19、 18、 17位都为0。
//PLLXTPER:HSE分频器作为PLL输入。此值为0,HSE不分频,那么PLLCLK=HSE
//PLLMUL:PLL倍频系数

 
  RCC->CIR = 0x009F0000;

 
 
  SetSysClock();
}

 


static void SetSysClockTo36(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
 
  //注释为:SYSLCK,HCLK,PCLK2和PCLK1 的配置  
 
     
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);//外部高速时钟允许
 
 
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++; 
  } while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut))
;//HSEStatus不为0时,外部高速时钟稳定了

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)//当外部高速时钟稳定时
  {
    HSEStatus = (uint32_t)0x01;//HSEStatus为1
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
 

  if (HSEStatus == (uint32_t)0x01)//当HSEStatus为1时,即外部高速时钟稳定时
  {
   
    FLASH->ACR |= FLASH_ACR_PRFTBE;

   
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1;   
 
   
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
     
   
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
   
   
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;

   
 //前面配置得到     PCLK1=PCLK2=HCLK=SYSCLK,那么,SYSCLK是多少呢? 下边配置SYSCLK值
   
   
   
    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_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL9);
//RCC_CFGR_PLLXTPRE_HSE_Div2:HSE   2分频以后作为PLL时钟,即PLLCLK输入=HSE/2
//RCC_CFGR_PLLMULL9:PLL   9倍频输出,即PLLCLK输出,也就是PLLCLK,它等于9倍的PLLCLK输入,即PLLCLK = (HSE / 2) * 9 = 36 MHz
//到这里,可以知道PLLCLK=36M
   
    RCC->CR |= RCC_CR_PLLON;

   
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }

   
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;   
      
 //前面要想得到的SYSCLK在这里就知道了。因为PLL输出作为系统时钟,即
 //SYSCLK=PLLCLK=36M
   
//程序中需要用的其他时钟也可以确定了。
//因为APB1 Prescaler=1(没有分频),所以TIMxCLK=PLCK1=36M
//因为APB2 Prescaler=1(没有分频),所以TIM1CLK=PLCK2=36M
//在SystemInit   中ADCPRE:ADC预分频 00:PCLK2 2分频后作为ADC时钟,即ADCCLK=PCLK2/2,所以ADCCLK=18M

 


    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
 
  else
  {

  }
}