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的工作過程,查閱參考手冊與庫函數的手使用冊可以自己進行的配置。

使用代碼再舉一個例子吧

  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. }  
發佈了3 篇原創文章 · 獲贊 31 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章