查看: 4558|回復: 0
打印 上一主題 下一主題

【CoX外設接口】CoX.SPI詳細講解

[復制鏈接]
跳轉到指定樓層
樓主
發(fā)表于 2013-1-21 08:51:15 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
關(guān)鍵詞: cox , spi , coocox
                          CoX.SPI接口設計思想  
1.1 CoX.SPI發(fā)展過(guò)程,歷史版本
     CoX1.0版本下的CoX.SPI是隨著(zhù)CoX第一版于2009年誕生而開(kāi)始的,在第一版中,我們首先實(shí)現了SPI模塊的主從模式的選擇和工作狀態(tài)的配置,單個(gè)字符的發(fā)送和接收以及數據流的發(fā)送和接收等功能。同樣我們也采用面向對象的方式,定義了一個(gè)通用的SPI的結構體。
typedef struct {
  COX_Status (*Init)       (uint8_t mode,     uint32_t rate);      
  uint32_t   (*Write)      (const void *wbuf,  uint32_t wlen);
  uint32_t   (*Read)      (void *rbuf,        uint32_t rlen);
  uint32_t   (*ReadWrite)  (uint32_t wdat);  
  COX_Status (*Cfg)       (uint8_t index,     uint32_t arg,    uint32_t *pre_arg);  
} COX_SPI_PI_Def;
    然后再實(shí)現基于CoX.SPI的對應不同廠(chǎng)商MCU的函接口數。
    當我們在實(shí)際編程中需要某個(gè)功能的時(shí)候,只需調用對應的CoX接口函數就可以了,而且由于CoX上層的函數名稱(chēng)的一致性,以利于系統將來(lái)的可移植性。有興趣的可以參考Coocox官網(wǎng)中NUC140-LB Board中的CoOS例程,鏈接地址:
    http://www.coocox.com/downloadfile/CoOS/Demo/NUC140_CoOS.zip。
    然而,在后來(lái)的開(kāi)發(fā)使用過(guò)程中,發(fā)現CoX1.0中SPI定義有幾個(gè)明顯的不足:
    1. 實(shí)現過(guò)程中考慮情況不全面。比如在第一版中SPI讀取和發(fā)送數據的方式只有阻塞式,這樣在遇到系統不需要強制讀取和發(fā)送數據的時(shí)候就無(wú)能為力了,同時(shí)還缺乏一些其他特殊的功能,比如SSn管腳配置的功能。
    2. 大量采用結構體的形式,使得代碼的可讀性大大降低,同時(shí)也降低了代碼的重用性,效率也不高。
    3. CoX API封裝不全面,僅僅實(shí)現了SPI初始化、配置、發(fā)送與接收的功能,在實(shí)現一些其它基本的功能時(shí),仍然需要結合對應的廠(chǎng)商庫來(lái)使用。
    鑒于CoX.SPI以上的幾種缺陷,經(jīng)常一年多時(shí)間的積累,在2011年開(kāi)始推出了CoX 2.0版本,這個(gè)版本解決了上述所有的缺點(diǎn)的同時(shí),還保留了CoX設計的初衷——那就是在Cortex-M系列CPU上面的通用性。下面,詳細介紹2.0版本下的CoX.SPI接口。

2. CoX2.0的SPI接口定義
    SPI通信模塊提供了用來(lái)處理器件和外圍設備的串行通信,可以配置成使用Motorola SPI 、Microwire或Texas Instrument同步串行接口的幀格式。數據幀的大小也可以配置。 SPI 模塊對接收到的外圍設備的數據執行串行-并行轉換,對發(fā)送給外圍設備的數據執行 并行-串行轉換,TX 和 RX 通路由內部 FIFO 進(jìn)行緩沖。 SPI 模塊可以配置成一個(gè)主機或一個(gè)從機設備。作為一個(gè)從機設備,SPI 模塊還能配置 成禁止它的輸出,這就允許一個(gè)主機設備與多個(gè)從機設備相連。 SPI 模塊還包含一個(gè)可編程的位速率時(shí)鐘分頻器和預分頻器來(lái)產(chǎn)生輸出串行時(shí)鐘(從 SPI 模塊的輸入時(shí)鐘獲得)。產(chǎn)生的位速率取決于輸入時(shí)鐘和連接的外設支持的最大位速率。 對于包含一個(gè) DMA 控制器的器件,SPI 模塊也提供一個(gè) DMA 接口以便通過(guò) DMA 來(lái) 實(shí)現數據傳輸。
    在設計SPI的CoX接口的時(shí)候,我們按著(zhù)SPI的功能劃分了幾個(gè)模塊,具體的設計思想如下:
   (1)SPI 工作狀態(tài)配置接口
       主模式/從模式的選擇
       數據流傳輸速率、數據寬度、數據移位方向的設置
       SSn管腳狀態(tài)的設置
       DMA模式的選擇
   (2)SPI 中斷控制接口
      使能/失能中斷
      中斷服務(wù)程序
   (3)SPI 數據發(fā)送與接收處理接口
      啟動(dòng)SPI數據發(fā)送和接收
      SPI數據發(fā)送與接收處理
    在設計CoX2.0-SPI的接口時(shí),我們充分考慮了基于Cortex-M內核的MCU中SPI所具有的大部分功能和SPI通信協(xié)議的特性,最終采用了通用強制性接口、通用非強制性接口和廠(chǎng)商庫接口這三種類(lèi)型的接口組合來(lái)共同完成SPI的接口定義,下面將分別對SPI的各個(gè)接口做介紹。

2.1通用強制接口
    通用強制接口是提取的一套ARM Cortex M0/M3所有廠(chǎng)商系列MCU都具有的功能接口。本篇將同樣以新唐M051為例講解CoX.SPI,其他系列大同小異。    SPI的APIs分組完成處理配置和狀態(tài)、處理數據和管理中斷幾大功能,CoX的宏定義的參數和APIs都是以' x '開(kāi)頭的, 函數和形式參數都是x開(kāi)頭,體現出CoX接口的特征。
   配置對應的GPIO管腳線(xiàn)為SPI功能的函數:
  • xSPinTypeSPIu SPI工作模式配置的函數:
  • xSPIConfigSetl xSPIEnablel xSPIDisablel xSPIDMAEnablel xSPIDMADisableu
  SSn管教狀態(tài)配置的函數:
  • xSPISSSetu 處理SPI中斷的APIs
  • xSPIIntCallbackInitl xSPIIntEnable
  • xSPIIntDisablel xSPIStatusGetu
  獲取SPI工作狀態(tài)的APIs
  • xSPIBitLengthGetl xSPIIsBusy
  • xSPIIsRxEmptyl xSPIIsTxEmpty
  • xSPIIsRxFulll xSPIIsTxFullu
  處理SPI的數據讀寫(xiě)的APIs
  • xSPISingleDataReadWrite
  • xSPIDataBufferRead
  • xSPIDataBufferReadNonBlocking
  • xSPIDataReadl xSPIDataBufferWrite
  • xSPIDataBufferWriteNonBlocking
  • xSPIDataWrite

2.2通用非強制接口
     通用非強制接口是一類(lèi)MCU通有的功能,而不是所有MCU都具有的功能接口:l xSPIErrorGetl xSPIErrorClear  

2.3廠(chǎng)商庫特色接口
    特色接口是包括了通用性接口,和MCU特有功能的接口。它并不是通用強制型或者通用非強制型,而是MCU特有的功能,就是在廠(chǎng)商庫特色接口這一組。相關(guān)的APIs接口如下:
  • SPIAutoSSEnablel SPIAutoSSDisable
  • SPISSClearl SPISSConfig
  • SPILevelTriggerStatusGet
  • SPIByteReorderSetl SPIVariableClockSet
  • SPIDivOneFunction
  • SPI3WireFunctionl SPI3WireAbort
  • SPI3WireStartIntEnable
  • SPI3WireStartIntDisable
  • SPI3WireStartIntFlagGet
  • SPI3WireStartIntFlagClear
    另外廠(chǎng)商庫接口也實(shí)現了MCU其他所有的功能,比如:
    SPIIntEnable(ulBase, ulIntFlags);
    也實(shí)現了SPI中斷使能/失能模式的配置,這個(gè)在CoX接口的xSPIIntEnable也是這個(gè)功能。其實(shí)這個(gè)時(shí)候xSPIIntEnable的實(shí)現方式如下:
#define xSPIIntEnable(ulBase,  ulIntFlags)                                     \
            SPIIntEnable(ulBase,  ulIntFlags)
   進(jìn)行了一次宏定義包裝罷了,對應的參數也是進(jìn)行的一次宏定義比如:
//
//! End of transfer
//
#define xSPI_INT_EOT            SPI_INT_EOT

3. 設計技巧簡(jiǎn)介
    SPI模塊的CoX接口在設計的過(guò)程中非常注重“上層應用簡(jiǎn)潔 下層驅動(dòng)通用”的核心思想, CoX.SPI組件提供了一套寄存器組件, 對所需要寫(xiě)入寄存器的值進(jìn)行了宏定義,這樣使得用戶(hù)在操作過(guò)程中不需深究寄存器的細節,使得配置更加直觀(guān),同時(shí)也方便用戶(hù)調用寄存器接口定義自己的功能函數。下面以函數xSPIConfigSet(ulBase, ulBitRate, ulConfig)為例來(lái)說(shuō)明:   
    比如將 MCU的SPI0模塊配置成Master Mode , polarity 0 , phase 0 , 200KHz, 8Bits Data width,  SPI MSB First模式, 代碼如下:                xSPIConfigSet(xSPI0_BASE,  200000,  xSPI_MOTO_FORMAT_MODE_0     |  
                                                                    xSPI_MODE_MASTER             |                                       
                                                                    xSPI_MSB_FIRST                    |                                       
                                                                    xSPI_DATA_WIDTH8);     
    xSPIConfigSet()函數的定義是  xSPIConfigSet(ulBase, ulBitRate, ulConfig)  ,其中ulBase對應SPIn的基地址,可以取值xSPI0_BASE、xSPI1_BASE、……,ulBitRate是SPI傳輸和接收數據的速率,ulConfig是SPI的各種工作狀態(tài)的組合。該函數的功能是非常豐富的,在執行完該函數后,SPI就完成了傳輸速率、數據格式、工作狀態(tài)等配置。具體的實(shí)現過(guò)程如下:
#define xSPIConfigSet(ulBase, ulBitRate, ulConfig)                                                             \        
           do                                                                                                                          \
           {                                                                                                                            \         
              SPIConfig(ulBase, ulBitRate, ulConfig);                                                                  \         
              SPISSConfig(ulBase, SPI_SS_LEVEL_TRIGGER, SPI_SS_ACTIVE_LOW_FALLING);\        
            }                                                                                                                            \        
           while(0)   
     (1)向SPI控制寄存器中分別寫(xiě)入數據格式、工作狀態(tài)、數據寬度等配置信息   
     (2)獲取SPI的系統時(shí)鐘,根據用戶(hù)設定的時(shí)鐘與獲取的SPI系統時(shí)鐘計算出分頻系數和分頻之后的值,然后將它們分別寫(xiě)入對應寄存器中。   
     (3)配置SSn管腳的觸發(fā)狀態(tài)。
    在這個(gè)功能函數中我們集成了兩個(gè)函數,其中SPIConfig(ulBase, ulBitRate, ulConfig)為廠(chǎng)商庫函數,這個(gè)接口剛好可以給CoX接口調用,做好相應的配置,不需要做特殊處理,這樣可以最大程度的重用代碼。同時(shí)為了方便用戶(hù),CoX.SPI會(huì )在初始化時(shí)選取一些默認狀態(tài)配置,例如SPISSConfig(ulBase, SPI_SS_LEVEL_TRIGGER, SPI_SS_ACTIVE_LOW_FALLING);這里默認將SS腳配置成了低電平觸發(fā), 符合MCU大部分工作狀態(tài)下SS管腳的配置,這樣不僅可以減少用戶(hù)的工作量,也使得代碼更簡(jiǎn)潔,當然用戶(hù)也可以使用CoX.SPI中的xSPISSSet()來(lái)自定義SS腳狀態(tài)。
    CoX.SPI另一個(gè)主要特色就是引入了阻塞式和非阻塞式的概念.我們在設計CoX.SPI接口的時(shí)候充分考慮實(shí)際編程的需求,相較于CoX1.0的數據處理,CoX2.0中特別增加了非阻塞式的數據發(fā)送和接收處理函數,可以滿(mǎn)足不同情況下的SPI數據發(fā)送與接收。具體的函數名稱(chēng)如下:
    非阻塞式發(fā)送:xSPIDataBufferWriteNonBlocking ()
    非阻塞式接收:xSPIDataBufferReadNonBlocking()
    阻塞式發(fā)送:xSPIDataBufferWrite()
    阻塞式接收:xSPIDataBufferRead()
    比如在一些采用循環(huán)查詢(xún)SPI數據的系統中,MCU會(huì )不停的循環(huán)查詢(xún)SPI的數據,這時(shí)如果我們采用一般的阻塞式的SPI數據接收,當SPI沒(méi)有接收數據時(shí),MCU會(huì )一直停在這等待,不斷的查詢(xún)SPI數據接收情況,而無(wú)法執行其他的任務(wù),這顯然不符合我們的要求,CoX1.0與廠(chǎng)商庫都不能很好的解決這一問(wèn)題,而在CoX2.0中,由于我們引入了非阻塞式數據接收與處理的概念,這個(gè)時(shí)候我們就可以采用非阻塞式的數據接收處理,讓單片機在查詢(xún)SPI數據為空時(shí),可以繼續執行下面的任務(wù),等待下次來(lái)再來(lái)查詢(xún)SPI數據狀態(tài),這樣就可以很好的解決等待SPI接收數據與運行其它任務(wù)之間的矛盾問(wèn)題。

4. SPI接口使用示例與移植
    下面給出一個(gè)CoX.SPI的示例,都是使用的通用強制型的接口,因此下面的例子在所有Cortex M0/M3上都是平滑移植的, 下面展示一個(gè)程序。
//
// Users should to modify the following GPIO pins definition when transplanting the different
//MCUs based on Cortex-M3/M0.
//
#define SPICLK_PIN        PB7
#define SPIMOSI_PIN        PB5
#define SPIMISO_PIN        PB6
#define SPICS_PIN                PB4
void SpiReceiveTransfer (void)
{
    //
    // Enable Peripheral SPI0
    //
    xSysCtlPeripheralEnable2(xGPIOSPinToPort(SPICLK_PIN));
    xSysCtlPeripheralEnable2(xSPI0_BASE);
    //
    // Set SysClk 36MHz using Extern 12M oscillator
    //
    xSysCtlClockSet(12000000, xSYSCTL_OSC_MAIN | xSYSCTL_XTAL_12MHZ);

    //
    // Configure Some GPIO pins as SPI Mode
    //
    xSPinTypeSPI(SPI0CLK, SPICLK _PIN);
    xSPinTypeSPI(SPI0MOSI, SPIMOSI _PIN);
    xSPinTypeSPI(SPI0MISO, SPIMISO _PIN);
    xSPinTypeSPI(SPI0CS, SPICS _PIN);
    xSPIConfigSet(xSPI0_BASE, 200000,  xSPI_FORMAT_MODE_0  |
                                                               xSPI_DATA_WIDTH32     |
                                                               xSPI_MSB_FIRST             |
                                                               xSPI_MODE_SLAVE);      
     while(1)
    {
        for(i = 0; i < 16; i++)
        {
            ulDestData = xSPISingleDataReadWrite(xSPI0_BASE, ulSourceData);
       }
    }
}


您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權所有   京ICP備16069177號 | 京公網(wǎng)安備11010502021702
快速回復 返回頂部 返回列表
午夜高清国产拍精品福利|亚洲色精品88色婷婷七月丁香|91久久精品无码一区|99久久国语露脸精品|动漫卡通亚洲综合专区48页