欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-09 08:54:44
...

1. 硬件平台

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

2. 实验目的

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

3. 配置原理

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

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); // 获取系统时钟配置
}

通过仿真可以查看各总线时钟的配置频率,如下图所示:
STM32在外部32Mhz晶振下的时钟配置方法
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 时钟配置