STM32F427xx系列芯片系统时钟讲解

STM32F427xx系列芯片系统时钟讲解
STM32F427xx系列芯片系统时钟讲解

STM32F427xx系列芯片系统时钟讲解

——写代码的Tobem 为了进行通用定时器的设置,有必要先了解STM32F427xx系列芯片的时钟系统。为了实现低功耗(对于每个时钟源来说,在未使用时都可单独打开或者关闭,以降低功耗),STM32F427xx设计了功能完善但却有点复杂的时钟系统,见下图:

图2 STM32F427xx系统时钟树

从图中可以看出,STM32F427xx具有4个时钟源,分别为2个内部时钟源和2个外部时钟源,也可以分为2个高速时钟源和2个低速时钟源,具体为:

1、HSE(高速外部时钟):以外部晶振作时钟源,晶振频率可取范围为4~26MHz,实际电路图中我们采用12MHz的晶振。

2、HSI(高速内部时钟):由内部RC振荡器产生,频率为16MHz。其特点是起振快,在芯片刚上电的时候,就是使用高速内部时钟,但其精度不高,因此,上电之后我们再通过软件配置(SystemInit()函数),转而采用高速外部时钟信号。

3、LSE(低速外部时钟):以外部晶振作时钟源,主要提供给实时时钟模块(RTC),一般采用32.768KHz。

4、LSI(低速内部时钟):由内部RC振荡器产生,频率为32KHz,主要用于驱动独立看门狗,也可选择提供给RTC 用于停机/待机模式下的自动唤醒。

程序在执行主函数main()之前,要先进行堆栈指针SP、程序计数器PC的初始化、设置异常中断向量地址等工作,最后才进入到主函数main()中去执行,这其中包括系统时钟的配置(在startup_stm32f4xx.s启动文件中)。系统时钟的配置由system_stm32f4xx.c文件中的SystemInit()函数完成,配置结果如下:

图3 系统时钟配置情况

从时钟树中可以看到,系统时钟SYSCLK是大部分器件的时钟来源,因此SYSCLK的配置就显得十分重要。SYSCLK可以从三个时钟源中进行选择,分别为HSI、HSE和PLLCLK。HSI 不稳定,而HSE速率太低(4~26MHz),为了使系统获得较快的运行速率和稳定性,我们选

择PLLCLK来作为SYSCLK(见备注1),而PLLCLK又可以选择HSI或者HSE作为时钟源,我们选择HSE作为时钟源(见备注2)

根据时钟树的走向,SYSCLK(即PLLCLK)计算过程为:

PLL_VCO = (HSE_VALUE / PLL_M) * PLL_N

SYSCLK = PLL_VCO / PLL_P

而宏定义有

#if !defined (HSE_VALUE)

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

#endif /* HSE_VALUE */

#define PLL_M 12

#define PLL_Q 7

#if defined (STM32F427_437xx) || defined (STM32F429_439xx)

#define PLL_N 360

#define PLL_P 2

故SYSCLK最终为180MHz。

注意:HSE_VALUE、PLL_M要根据实际使用的外部晶振来确定取值。

备注1:SYSCLK时钟源的选择:

系统时钟源的选择由RCC时钟配置寄存器的SW(位1:0)来决定:

在程序中,通过(RCC->CFGR & RCC_CFGR_SWS)进行选择判断,当(RCC->CFGR & RCC_CFGR_SWS)为0x08时,则选择PLLSCK作为系统时钟源。stm32f4xx_rcc.c文件中的void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource)函数可完成对RCC->CFGR 的低二位进行设置。

#define RCC_CFGR_SW ((uint32_t)0x00000003)

#define RCC_CFGR_SWS ((uint32_t)0x0000000C)

#define RCC_CFGR_SWS_PLL ((uint32_t)0x00000008)

#define RCC_SYSCLKSource_PLLCLK ((uint32_t)0x00000002)

#define IS_RCC_SYSCLK_SOURCE(SOURCE) (((SOURCE) == RCC_SYSCLKSource_HSI) || \

((SOURCE) == RCC_SYSCLKSource_HSE) || \

((SOURCE) == RCC_SYSCLKSource_PLLCLK)) assert_param(IS_RCC_SYSCLK_SOURCE(RCC_SYSCLKSource));

/* Select the main PLL as system clock source */

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

RCC->CFGR |= RCC_CFGR_SW_PLL;

RCC->CFGR上电之后初始值为0x00000000,因此经过上述运算后,

RCC->CFGR=0x0000000A,故(RCC->CFGR & RCC_CFGR_SWS)为0x00000008。

详见system_stm32f4xx.c文件中的void SystemCoreClockUpdate(void)函数。

备注2:PLLSCK时钟源的选择:

程序中,PLLSCK的时钟源由pllsource来进行判断选择,当pllsource不为0时,则选择HSE 作为PLL的时钟源;否则,选择HSI作为PLL的时钟源:

#define PLL_M 12

#define PLL_Q 7

#if defined (STM32F427_437xx) || defined (STM32F429_439xx)

#define PLL_N 360

#define PLL_P 2

#endif /* STM32F427_437x || STM32F429_439xx */

#define RCC_PLLCFGR_PLLSRC ((uint32_t)0x00400000)

#define RCC_PLLCFGR_PLLSRC_HSE ((uint32_t)0x00400000)

#define RCC_PLLCFGR_PLLSRC_HSI ((uint32_t)0x00000000)

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

(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);

pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;

经过上述计算,pllsource=1,不为0,因此选择HSE作为PLL的时钟源。

详见system_stm32f4xx.c文件中的void SystemCoreClockUpdate(void)函数。

相关主题
相关文档
最新文档