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

STM32系统时钟配置及时钟树

发布时间:2020-06-06 发布时间:
|

参考资料:《 STM32F4xx 中文参考手册》 RCC 章节。


STM32时钟可大致分为系统时钟和其它时钟两大类,总共包含5个时钟源 HSI(High Speed Internal Clock)、HSE(High Speed External Clock)、LSI(low Speed Internal Clock)、LSE(Low Speed External Clock )、PLL(Phase Locked Loop Clock)。


下图即为STM32时钟树,黄色标识部分即为系统时钟部分,橙色即为其它时钟部分。



一、系统时钟


①HSE(High Speed External Clock)高速外部时钟信号



HSE 是高速的外部时钟信号,可以由有源晶振或者无源晶振提供,频率从 4-26MHZ不等。当使用有源晶振时,时钟从 OSC_IN引脚进入,OSC_OUT 引脚悬空,当选用无源晶振时,时钟从 OSC_IN 和 OSC_OUT 进入,并且要配谐振电容。HSE 我们使用25M 的无源晶振。如果我们使用 HSE 或者 HSE 经过 PLL倍频之后的时钟作为系统时钟 SYSCLK,当 HSE 故障时候,不仅HSE 会被关闭,PLL也会被关闭,此时高速的内部时钟时钟信号HSI 会作为备用的系统时钟,直到 HSE 恢复正常,HSI=16M。


HSI(High Speed Internal Clock)高速内部时钟信号



由芯片内部RC振荡器提供,大小为16MHZ,当HSE故障时,系统时钟会自动切换到HSI,直到HSE 启动成功。


②锁相环 PLL(Phase Locked Loop )



PLL的主要作用是对时钟进行倍频,然后把时钟输出到各个功能部件。PLL有两个,一个是主 PLL(黄色部分,为系统时钟部分),另外一个是专用的 PLLI2S(橙色部分),他们均由 HSE 或者 HSI 提供时钟输入信号。


主 PLL有两路的时钟输出,第一个输出时钟 PLLCLK用于系统时钟,第二个输出用于 USB OTG FS 的时钟、RNG 和 SDIO 时钟。专用的 PLLI2S 用于生成精确时钟,给 I2S 提供时钟。


HSE 或者 HSI 经过 PLL 时钟输入分频因子 M分频后,成为 VCO 的时钟输入,VCO 的时钟必须在 1~2M 之间,我们选择HSE=25M 作为 PLL 的时钟输入,M 设置为 25,那么 VCO输入时钟就等于 1M。VCO 输入时钟经过 VCO倍频因子 N 倍频之后,成为 VCO时钟输出,VCO时钟必须在 192~432M 之间。我们配置 N 为 360,则 VCO的输出时钟等于 360M。VCO 输出时钟之后有三个分频因子:PLLCLK分频因子 p,USB OTG FS/RNG/SDIO时钟分频因子 Q,分频因子R


具体公式如下


                                                             PLLCLK = HSE(HSI) / M *N /P 


                                                             PLL48CK =  HSE(HSI) / M *N /Q


③系统时钟 SYSCLK



系统时钟来源可以是:HSI、PLLCLK、HSE,具体的由时钟配置寄存器 RCC_CFGR的 SW位配置。如果系统时钟是由HSE 经


过 PLL倍频之后的 PLLCLK 得到,当 HSE 出现故障的时候,系统时钟会切换为HSI=16M,直到 HSE 恢复正常为止。


④AHB 总线时钟 HCLK



系统时钟 SYSCLK 经过 AHB 预分频器分频之后得到时钟叫 AHB 总线时钟,即 HCLK,分频因子可以是:[1,2,4,8,16,64,


128,256,512],具体的由时钟配置寄存器RCC_CFGR 的 HPRE 位设置。片上大部分外设的时钟都是经过 HCLK 分频得到,


至于 AHB总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置。这里只需粗线条的设置好AHB的时钟即可。


⑤APB2总线时钟 PCLK2



APB2总线时钟 PCLK2 由 HCLK经过高速 APB2预分频器得到,分频因子可以是:[1,2,4,8,16],具体由时钟配置寄存器RCC_CFGR 的 PPRE2位设置。HCLK2属于高速的总线时钟,片上高速的外设就挂载到这条总线上,比如全部的 GPIO、USART1、SPI等。至于 APB2总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置。这里只需粗线条的设置好APB2的时钟即可。


⑥APB1总线时钟 PCLK1


APB1 总线时钟 PCLK1 由 HCLK经过低速 APB预分频器得到,分频因子可以是:[1,2,4,8,16],具体由时钟配置寄存器RCC_CFGR的 PPRE1位设置。HCLK1属于低速的总线时钟,最高为 45M,片上低速的外设就挂载到这条总线上,比如USART2/3/4/5、SPI2/3,I2C1/2等。至于 APB1总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置。


这里只需粗线条的设置好APB的时钟即可。


系统初始化时钟过程如下


Reset_Handler    PROC

                 EXPORT  Reset_Handler             [WEAK]

        IMPORT  SystemInit

        IMPORT  __main

 

                 LDR     R0, =SystemInit

                 BLX     R0

                 LDR     R0, =__main

                 BX      R0

                 ENDP


这是一个启动文件,当我们单片机上电后,首先执行的启动文件,会进入SystemInit函数


void SystemInit(void)

{

  /* FPU设置 ------------------------------------------------------------*/

  #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)

    SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */

  #endif

  /* 复位RCC时钟配置到默认的初始化状态 ------------*/

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

 

#if defined(DATA_IN_ExtSRAM) || defined(DATA_IN_ExtSDRAM)

  SystemInit_ExtMemCtl(); 

#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */

         

  /* 配置系统时钟 ----------------------------------*/

  SetSysClock();

 

  /* Configure the Vector Table location add offset address ------------------*/

#ifdef VECT_TAB_SRAM

  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */

#else

  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */

#endif

}

在SystemInit中会配置系统时钟


配置系统时钟的代码如下



下面是CMSIS Cortex-M4设备外围设备访问层系统源文件中的设置系统时钟函数SetSysClock(void)


static void SetSysClock(void)

{

 

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

/*            使用HSE作为PLL的输入来配置系统时钟                                */

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

  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

  

  /* 一、使能HSE */

  RCC->CR |= ((uint32_t)RCC_CR_HSEON);

 

  /* 等待HSE使能稳定,如果时间超时,则跳出 */

  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;

  }

/*二、HSE稳定后,开始配置HCLK、PCLK2、PCLK1、PLL各自的预分频因子与倍频因子 */

  if (HSEStatus == (uint32_t)0x01)

  {



/* 配置HCLK为1分频,即HCLK = 系统时钟 HCLK = SYSCLK / 1 */

RCC->CFGR |= RCC_CFGR_HPRE_DIV1;

    

/*配置APB2总线时钟为2分频  PCLK2 = HCLK / 2 */

RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;


/*配置APB1总线时钟为4分频PCLK1 = HCLK / 4 */

RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;

   

/* 配置主PLL */

RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |

(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);

   

    /* 三、使能主PLL */

    RCC->CR |= RCC_CR_PLLON;

 

    /*等待主PLL稳定 */

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

    {

    }

/*------------------------------------------------------------------------------------------*/    

/* 使能Over-drive 模式来达到更高的时钟频率 */

PWR->CR |= PWR_CR_ODEN;

while((PWR->CSR & PWR_CSR_ODRDY) == 0)        //判断Over-drive模式是否已经成功启动

{

}

PWR->CR |= PWR_CR_ODSWEN;

while((PWR->CSR & PWR_CSR_ODSWRDY) == 0)

{

}      

/*选择FLASH预取指缓存的模式, 指令缓存, 数据缓存和等待缓存 */

FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;

/*------------------------------------------------------------------------------------------*/


    /* 四、选择主PLL作为系统时钟源 */

    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));

    RCC->CFGR |= RCC_CFGR_SW_PLL;

 

    /*判断系统时钟是否已经稳定 */

    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);

    {

    }

  }

  else

  { /* 如果HSE启动失败,那么时钟就会被错误的配置,用户可以在这里添加一些代码来处理错误 */

  }

 

}

系统时钟配置主要就是以上部分,系统时钟初始化就进行的是上述操作.


 


二、其它时钟


A、RTC时钟



RTCCLK 时钟源可以是 HSE 1 MHz( HSE 由一个可编程的预分频器分频)、 LSE 或者 LSI 时钟。选择方式是编程 RCC 备份


域控制寄存器 (RCC_BDCR) 中的 RTCSEL[1:0] 位和 RCC时钟配置寄存器 (RCC_CFGR) 中的 RTCPRE[4:0] 位。所做的选择只


能通过复位备份域的方式修改。我们通常的做法是由 LSE 给 RTC提供时钟,大小为 32.768KHZ。LSE由外接的晶体谐振器产生,


所配的谐振电容精度要求高,不然很容易不起震。


B、独立看门狗时钟



独立看门狗时钟由内部的低速时钟 LSI 提供,大小为 32KHZ。


C、I2S 时钟



I2S 时钟可由外部的时钟引脚 I2S_CKIN 输入,也可由专用的 PLLI2SCLK提供,具体的由 RCC 时钟配置寄存器 (RCC_CFGR)的 I2SSCR位配置。


D、PHY以太网时钟



F429要想实现以太网功能,除了有本身内置的 MAC之外,还需要外接一个 PHY 芯片,常见的 PHY 芯片有 DP83848和LAN8720,其中 DP83848支持 MII 和 RMII 接口,LAN8720只支持 RMII 接口。野火 F429 开发板用的是 RMII 接口,选择的PHY 芯片是LAB8720。使用 RMII 接口的好处是使用的 IO 减少了一半,速度还是跟 MII 接口一样。当使用 RMII 接口时,PHY芯片只需输出一路时钟给 MCU 即可,如果是 MII 接口,PHY 芯片则需要提供两路时钟给 MCU。


E、USB PHY 时钟



F429 的 USB 没有集成 PHY,要想实现 USB 高速传输的话,必须外置 USB PHY 芯片,常用的芯片是 USB3300。当外接 USBPHY 芯片时,PHY 芯片需要给 MCU 提供一个时钟。


F、MCO时钟输出



MCO 是 microcontroller clock output 的缩写,是微控制器时钟输出引脚,主要作用是可以对外提供时钟,相当于一个有源晶振。


F429中有两个 MCO,由 PA8/PC9复用所得。MCO1所需的时钟源通过 RCC 时钟配置寄存器 (RCC_CFGR) 中MCO1PRE[2:0]


和MCO1[1:0]位选择。MCO2所需的时钟源通过 RCC 时钟配置寄存器 (RCC_CFGR) 中的MCO2PRE[2:0] 和 MCO2位选择。


以上就是STM32f429的时钟树讲解,理解之后,以此类推,对于学习STM32其它时钟树有很大的帮助。




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

热门文章 更多
C51 特殊功能寄存器SFR的名称和地址