×
单片机 > 单片机程序设计 > 详情

STM32在外部32Mhz晶振下的时钟配置方法

发布时间:2020-07-08 发布时间:
|

1. 硬件平台


本例程使用的是 STM32F302RDT6 芯片,其时钟配置方法在其它ST单片机中也类似。

2. 实验目的


使用外部 32Mhz 晶振配置系统时钟为 72Mhz。

3. 配置原理


根据STM32F302RD芯片的参考手册,可以查看该芯片的时钟树结构,这里我们配置系统时钟 SYSCLK 为72Mhz,所以这里只需要修改 PREDIV 的分频值为4分频,其它 PLL 倍频等配置和使用8Mhz外部晶振时配置相同。 

4. 修改配置

(1)打开工程里的 system_stm32f30x.c 文件,找到 SetSysClock() 函数,进行时钟配置修改。这里我们只需要将外部时钟四分频后得到8Mhz的时钟,所示我们只需要添加 RCC->CFGR2 |= (uint32_t)RCC_CFGR2_PREDIV1_DIV4;来实现时钟的分频。

static void SetSysClock(void)

{

  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;


/******************************************************************************/

/*            PLL (clocked by HSE) used as System clock source                */

/******************************************************************************/


  /* 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 and set Flash Latency */

    FLASH->ACR = FLASH_ACR_PRFTBE | (uint32_t)FLASH_ACR_LATENCY_1;


     /* HCLK = SYSCLK / 1 */

     RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;


     /* PCLK2 = HCLK / 1 */

     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;


     /* PCLK1 = HCLK / 2 */

     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;


    /* PLL configuration */

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

    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL9);


    /*!< PREDIV1 input clock divided by 4 */  

    RCC->CFGR2 |= (uint32_t)RCC_CFGR2_PREDIV1_DIV4;     // add. by zhixiaoxing


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

  }

}


(2)全局搜索 HSE_VALUE 空定义,在 stm32f30x.h 文件中,这里我们将外部晶振时钟修改为 32000000 Hz


#if !defined  (HSE_VALUE) 

#define HSE_VALUE            ((uint32_t)32000000) /*!< Value of the External oscillator in Hz */

#endif /* HSE_VALUE */


5. 查看总线时钟


在对STM32时钟进行配置后,为了进一步验证配置的正确性,我们可以使用仿真来查看系统各总线的时钟频率。首先在主函数中添加如下代码:


int main(void)

{

    RCC_ClocksTypeDef get_rcc_clock;    

    RCC_GetClocksFreq(&get_rcc_clock); // 获取系统时钟配置

}

通过仿真可以查看各总线时钟的配置频率,如下图所示: 
 
Note:注意一定要修改宏 #define HSE_VALUE ((uint32_t)32000000) /!< Value of the External oscillator in Hz /的值,因为时钟使用该宏定义进行计算。

5. 慎入此坑


在时钟配置时,需要注意的一些问题: 

(1)在时钟树任何一个倍频的环节都不能超频,即使后面分频系数较大,还是会导致时钟配置失败; 

(2)在配置外部晶振四分频时,发现了一个诡异的问题,CFGR2寄存器一定要在CFGR寄存器之后,否则会导致CGFR2寄存器的值与配置的不符,至今不明其诡异之处?


/* PLL configuration */

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

RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL9);


/*!< PREDIV1 input clock divided by 4 */  

RCC->CFGR2 |= (uint32_t)RCC_CFGR2_PREDIV1_DIV4;     // add. by zhixiaoxing




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32单片机的复用端口初始化的步骤及方法