STM32笔记:RCC结构与配置流程

        以前使用STM32写程序的时候,使用的都是默认时钟。因此写数码管显示、A/D测量电压的时候都没有去关心RCC时钟配置这个事情。那时候只知道在配置外设的时候使用GPIO_InitTypeDef或者ADC_InitTypeDef这些结构体对外设进行初始化,以及使用RCC_APB2PeriphClockCmd或者RCC_ADCCLKConfig函数对外设的时钟开启与配置。

        这几天尝试使用STM32的USB通信写一个鼠标,发现一些例程中有关于时钟配置的代码,才注意起这个事情。为此进行了一些学习,并且记录如下的笔记。

一、RCC的结构

        以下是STM32时钟系统的结构图: 

        从图中,我们可以看到,STM32的时钟有四个来源:外部晶振提供的高速外部时钟(HSE)、外部晶振提供的低速外部时钟(LSE)、内部RC振荡器提供的高速内部时钟(HSI)、内部RC振荡器提供的低速内部时钟(LSI)。看上去RCC的工作过程好像很复杂,其实细看并不然。

        举个例子吧,Keil编写程序是默认的时钟为72Mhz,其实是这么来的:外部晶振提供的8MHz(与电路板上的晶振的相关)通过PLLXTPRE分频器后,进入PLLSRC选择开关,进而通过PLLMUL锁相环进行倍频(x9)后,为系统提供72MHz的系统时钟(SYSCLK)。之后是AHB预分频器对时钟信号进行分频,然后为低速外设提供时钟。

        当然,在实际应用中,我们也可以为系统时钟作其他的设置。譬如把内部高速RC振荡器(HSI RC)二分频后,通过PLLSRC选择开关进行倍频而不使用外部晶振作为输入,HSI也可以直接通过SW选择开关来提供系统时钟。

        此外,STM32还提供了一个时钟监视系统(CSS),用于监视高速外部时钟(HSE)的工作状态。倘若HSE失效,会自动切换(高速内部时钟)HSI作为系统时钟的输入。


二、RCC配置流程

1、将RCC寄存器恢复为默认值   RCC_DeInit
2、打开外部高速时钟晶振    RCC_HSEConfig
3、等待外部高速时钟晶振工作  
4、设置AHB时钟    RCC_HCLKConfig
5、设置高速APB时钟    RCC_PCLK2Config
6、设置低速APB时钟    RCC_PCLK1Config
7、设置PLL锁相环    RCC_PLLConfig
8、打开PLL锁相环    RCC_PLLCmd
9、等待PLL锁相环工作    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)
10、设置系统时钟    RCC_SYSCLKConfig
11、判断PLL是否为系统时钟    while(RCC_GetSYSCLKSource()!=0x08)
12、打开要使用的外设时钟 RCC_APB2PeriphClockCmd/RCC_APB1PeriphClockCmd

以上步骤只是举个例子。根据RCC的工作过程,查阅参考手册与库函数的手使用册可以自己进行的配置。

使用代码再举一个例子吧

void RCC_Configuration(void)
{
	//----------使用外部RC晶振-----------
	RCC_DeInit();			//初始化为缺省值
	RCC_HSEConfig(RCC_HSE_ON);	//使能外部的高速时钟 
	while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);	//等待外部高速时钟使能就绪
	
	FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);	//Enable Prefetch Buffer
	FLASH_SetLatency(FLASH_Latency_2);		//Flash 2 wait state
	
	RCC_HCLKConfig(RCC_SYSCLK_Div1);		//HCLK = SYSCLK
	RCC_PCLK2Config(RCC_HCLK_Div1);			//PCLK2 =  HCLK
	RCC_PCLK1Config(RCC_HCLK_Div2);			//PCLK1 = HCLK/2
	RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);	//PLLCLK = 8MHZ * 9 =72MHZ
	RCC_PLLCmd(ENABLE);			//Enable PLLCLK

	while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);	//Wait till PLLCLK is ready
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);	//Select PLL as system clock
	while(RCC_GetSYSCLKSource()!=0x08);		//Wait till PLL is used as system clock source
	
	//---------打开相应外设时钟--------------------
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	//使能APB2外设的GPIOA的时钟		 
}



猜你喜欢

转载自blog.csdn.net/u014695839/article/details/52474730