welcom ! Handel home

2014年6月17日 星期二

ST32 RCC Timer contorl 說明



                                                     STM32
時鐘控制RCC
對於單片機系統來說,CPU和匯流排以及外設的時鐘設置是非常重要的,因為沒有時鐘就沒有時序,組合電路能幹什麼想必各位心裡都清楚。其實時鐘的學習這部分應該提前一些,但由於一開始時間比較短,有些急於求成,所以直接使用了萬利給的常式,姑且跳過了這一步。介於下面我計畫要學習的任務都涉及到兆級的高速傳輸,例如全速USBDMA等等,所以不能再忽略時鐘啦,必須要仔細研究一下。
我學習RCC的參考資料:
技術文檔0427及其中文翻譯版STM32F10xxx_Library_Manual_ChineseV2的第十五章和RM0008_CH參考手冊。
準備知識:
片上匯流排標準種類繁多,而由ARM公司推出的AMBA片上匯流排受到了廣大IP開發商和SoC系統集成者的青睞,已成為一種流行的工業標準片上結構。AMBA規範主要包括了AHB(Advanced High performance Bus)系統匯流排和APB(Advanced Peripheral Bus)週邊匯流排。二者分別適用於高速與相對低速設備的連接。
由於時鐘是一個由內而外的東西,具體設置要從寄存器開始。

RCC 
寄存器結構,RCC_TypeDeff,在檔“stm32f10x_map.h”中定義如下: 
typedef struct 

   vu32 CR; 
   vu32 CFGR; 
   vu32 CIR; 
   vu32 APB2RSTR; 
   vu32 APB1RSTR; 
   vu32 AHBENR; 
   vu32 APB2ENR; 
   vu32 APB1ENR; 
   vu32 BDCR; 
   vu32 CSR; 
} RCC_TypeDef;
這些寄存器的具體定義和使用方式參見晶片手冊,在此不贅述,因為C語言的開發可以不和他們直接打交道,當然如果能夠加以理解和記憶,無疑是百利而無一害。
相信細心的朋友早就發現板子上只有8Mhz的晶振,而增強型最高工作頻率為72Mhz,顯然需要用PLL倍頻9倍,這些設置都需要在初始化階段完成。為了方便說明,我借用一下常式的RCC設置函數,並用中文注釋的形式加以說明:

/*******************************************************************************
* Function Name : Set_System
* Description    : Configures Main system clocks & power
* Input          : None.
* Return         : None.
*******************************************************************************/
//
在此指出上面的注釋頭應該是複製過來的,寫錯了...不過沒關係,反正沒參數需要說明,重要的是函數體。
static void RCC_Config(void)
{

/* 
這裡是重置了RCC的設置,類似寄存器復位 */
RCC_DeInit();

/* 
使能外部高速晶振 */
RCC_HSEConfig(RCC_HSE_ON);

/* 
等待高速晶振穩定 */
HSEStartUpStatus = RCC_WaitForHSEStartUp();

if (HSEStartUpStatus == SUCCESS)
{
    /* 
使能flash預讀取緩衝區 */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

    /* 
Flash處於等候狀態,2是針對高頻時鐘的,這兩句跟RCC沒直接關係,可以暫且略過 */
    FLASH_SetLatency(FLASH_Latency_2);

    /* HCLK = SYSCLK 
設置高速匯流排時鐘=系統時鐘*/
    RCC_HCLKConfig(RCC_SYSCLK_Div1);

    /* PCLK2 = HCLK 
設置低速匯流排2時鐘=高速匯流排時鐘*/
    RCC_PCLK2Config(RCC_HCLK_Div1);

    /* PCLK1 = HCLK/2 
設置低速匯流排1的時鐘=高速時鐘的二分頻*/
    RCC_PCLK1Config(RCC_HCLK_Div2);

    /* ADCCLK = PCLK2/6 
設置ADC外設時鐘=低速匯流排2時鐘的六分頻*/
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);

    /* Set PLL clock output to 72MHz using HSE (8MHz) as entry clock */ 
    //
上面這句常式中缺失了,但卻很關鍵
    /* 
利用鎖相環講外部8Mhz晶振9倍頻到72Mhz */ 
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); 

    /* Enable PLL 
使能鎖相環*/
    RCC_PLLCmd(ENABLE); 


    /* Wait till PLL is ready 
等待鎖相環輸出穩定*/
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {}

    /* Select PLL as system clock source 
將鎖相環輸出設置為系統時鐘 */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source 
等待校驗成功*/
    while (RCC_GetSYSCLKSource() != 0x08)
    {}
}

    /* Enable FSMC, GPIOD, GPIOE, GPIOF, GPIOG and AFIO clocks */
    //
使能週邊介面匯流排時鐘,注意各外設的隸屬情況,不同晶片的分配不同,到時候查手冊就可以
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |
                         RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG |
                         RCC_APB2Periph_AFIO, ENABLE);
}
由上述程式可以看出系統時鐘的設定是比較複雜的,外設越多,需要考慮的因素就越多。同時這種設定也是有規律可循的,設定參數也是有順序規範的,這是應用中應當注意的,例如PLL的設定需要在使能之前,一旦PLL使能後參數不可更改。
經過此番設置後,由於我的電路板上是8Mhz晶振,所以系統時鐘為72Mhz,高速匯流排和低速匯流排2都為72Mhz,低速匯流排136MhzADC時鐘為12MhzUSB時鐘經過1.5分頻設置就可以實現48Mhz的資料傳輸。
一般性的時鐘設置需要先考慮系統時鐘的來源,是內部RC還是外部晶振還是外部的振盪器,是否需要PLL。然後考慮內部匯流排和外部匯流排,最後考慮外設的時鐘信號。遵從先倍頻作為CPU時鐘,然後在由內向外分頻,下級遷就上級的原則有點兒類似PCB製圖的規範化要求,在這裡也一樣。




沒有留言: