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

来源:互联网 发布:山东大学经济学知乎 编辑:程序博客网 时间:2024/06/04 20:10

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的工作过程,查阅参考手册与库函数的手使用册可以自己进行的配置。

使用代码再举一个例子吧

[cpp] view plain copy
  1. void RCC_Configuration(void)  
  2. {  
  3.     //----------使用外部RC晶振-----------  
  4.     RCC_DeInit();           //初始化为缺省值  
  5.     RCC_HSEConfig(RCC_HSE_ON);  //使能外部的高速时钟   
  6.     while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); //等待外部高速时钟使能就绪  
  7.       
  8.     FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);   //Enable Prefetch Buffer  
  9.     FLASH_SetLatency(FLASH_Latency_2);      //Flash 2 wait state  
  10.       
  11.     RCC_HCLKConfig(RCC_SYSCLK_Div1);        //HCLK = SYSCLK  
  12.     RCC_PCLK2Config(RCC_HCLK_Div1);         //PCLK2 =  HCLK  
  13.     RCC_PCLK1Config(RCC_HCLK_Div2);         //PCLK1 = HCLK/2  
  14.     RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); //PLLCLK = 8MHZ * 9 =72MHZ  
  15.     RCC_PLLCmd(ENABLE);         //Enable PLLCLK  
  16.   
  17.     while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //Wait till PLLCLK is ready  
  18.     RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);  //Select PLL as system clock  
  19.     while(RCC_GetSYSCLKSource()!=0x08);     //Wait till PLL is used as system clock source  
  20.       
  21.     //---------打开相应外设时钟--------------------  
  22.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);    //使能APB2外设的GPIOA的时钟        
  23. }  
原创粉丝点击