電子工程網(wǎng)
標(biāo)題: 【CoX外設(shè)接口】CoX.SPI詳細(xì)講解 [打印本頁(yè)]
作者: coocox 時(shí)間: 2013-1-21 08:51
標(biāo)題: 【CoX外設(shè)接口】CoX.SPI詳細(xì)講解
CoX.SPI接口設(shè)計(jì)思想
1.1 CoX.SPI發(fā)展過程,歷史版本
CoX1.0版本下的CoX.SPI是隨著CoX第一版于2009年誕生而開始的,在第一版中,我們首先實(shí)現(xiàn)了SPI模塊的主從模式的選擇和工作狀態(tài)的配置,單個(gè)字符的發(fā)送和接收以及數(shù)據(jù)流的發(fā)送和接收等功能。同樣我們也采用面向?qū)ο蟮姆绞剑x了一個(gè)通用的SPI的結(jié)構(gòu)體。
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í)現(xiàn)基于CoX.SPI的對(duì)應(yīng)不同廠商MCU的函接口數(shù)。
當(dāng)我們?cè)趯?shí)際編程中需要某個(gè)功能的時(shí)候,只需調(diào)用對(duì)應(yīng)的CoX接口函數(shù)就可以了,而且由于CoX上層的函數(shù)名稱的一致性,以利于系統(tǒng)將來的可移植性。有興趣的可以參考Coocox官網(wǎng)中NUC140-LB Board中的CoOS例程,鏈接地址:
http://www.coocox.com/downloadfile/CoOS/Demo/NUC140_CoOS.zip。
然而,在后來的開發(fā)使用過程中,發(fā)現(xiàn)CoX1.0中SPI定義有幾個(gè)明顯的不足:
1. 實(shí)現(xiàn)過程中考慮情況不全面。比如在第一版中SPI讀取和發(fā)送數(shù)據(jù)的方式只有阻塞式,這樣在遇到系統(tǒng)不需要強(qiáng)制讀取和發(fā)送數(shù)據(jù)的時(shí)候就無能為力了,同時(shí)還缺乏一些其他特殊的功能,比如SSn管腳配置的功能。
2. 大量采用結(jié)構(gòu)體的形式,使得代碼的可讀性大大降低,同時(shí)也降低了代碼的重用性,效率也不高。
3. CoX API封裝不全面,僅僅實(shí)現(xiàn)了SPI初始化、配置、發(fā)送與接收的功能,在實(shí)現(xiàn)一些其它基本的功能時(shí),仍然需要結(jié)合對(duì)應(yīng)的廠商庫(kù)來使用。
鑒于CoX.SPI以上的幾種缺陷,經(jīng)常一年多時(shí)間的積累,在2011年開始推出了CoX 2.0版本,這個(gè)版本解決了上述所有的缺點(diǎn)的同時(shí),還保留了CoX設(shè)計(jì)的初衷——那就是在Cortex-M系列CPU上面的通用性。下面,詳細(xì)介紹2.0版本下的CoX.SPI接口。
2. CoX2.0的SPI接口定義
SPI通信模塊提供了用來處理器件和外圍設(shè)備的串行通信,可以配置成使用Motorola SPI 、Microwire或Texas Instrument同步串行接口的幀格式。數(shù)據(jù)幀的大小也可以配置。 SPI 模塊對(duì)接收到的外圍設(shè)備的數(shù)據(jù)執(zhí)行串行-并行轉(zhuǎn)換,對(duì)發(fā)送給外圍設(shè)備的數(shù)據(jù)執(zhí)行 并行-串行轉(zhuǎn)換,TX 和 RX 通路由內(nèi)部 FIFO 進(jìn)行緩沖。 SPI 模塊可以配置成一個(gè)主機(jī)或一個(gè)從機(jī)設(shè)備。作為一個(gè)從機(jī)設(shè)備,SPI 模塊還能配置 成禁止它的輸出,這就允許一個(gè)主機(jī)設(shè)備與多個(gè)從機(jī)設(shè)備相連。 SPI 模塊還包含一個(gè)可編程的位速率時(shí)鐘分頻器和預(yù)分頻器來產(chǎn)生輸出串行時(shí)鐘(從 SPI 模塊的輸入時(shí)鐘獲得)。產(chǎn)生的位速率取決于輸入時(shí)鐘和連接的外設(shè)支持的最大位速率。 對(duì)于包含一個(gè) DMA 控制器的器件,SPI 模塊也提供一個(gè) DMA 接口以便通過 DMA 來 實(shí)現(xiàn)數(shù)據(jù)傳輸。
在設(shè)計(jì)SPI的CoX接口的時(shí)候,我們按著SPI的功能劃分了幾個(gè)模塊,具體的設(shè)計(jì)思想如下:
(1)SPI 工作狀態(tài)配置接口
主模式/從模式的選擇
數(shù)據(jù)流傳輸速率、數(shù)據(jù)寬度、數(shù)據(jù)移位方向的設(shè)置
SSn管腳狀態(tài)的設(shè)置
DMA模式的選擇
(2)SPI 中斷控制接口
使能/失能中斷
中斷服務(wù)程序
(3)SPI 數(shù)據(jù)發(fā)送與接收處理接口
啟動(dòng)SPI數(shù)據(jù)發(fā)送和接收
SPI數(shù)據(jù)發(fā)送與接收處理
在設(shè)計(jì)CoX2.0-SPI的接口時(shí),我們充分考慮了基于Cortex-M內(nèi)核的MCU中SPI所具有的大部分功能和SPI通信協(xié)議的特性,最終采用了通用強(qiáng)制性接口、通用非強(qiáng)制性接口和廠商庫(kù)接口這三種類型的接口組合來共同完成SPI的接口定義,下面將分別對(duì)SPI的各個(gè)接口做介紹。
2.1通用強(qiáng)制接口
通用強(qiáng)制接口是提取的一套ARM Cortex M0/M3所有廠商系列MCU都具有的功能接口。本篇將同樣以新唐M051為例講解CoX.SPI,其他系列大同小異。 SPI的APIs分組完成處理配置和狀態(tài)、處理數(shù)據(jù)和管理中斷幾大功能,CoX的宏定義的參數(shù)和APIs都是以' x '開頭的, 函數(shù)和形式參數(shù)都是x開頭,體現(xiàn)出CoX接口的特征。
配置對(duì)應(yīng)的GPIO管腳線為SPI功能的函數(shù):
- xSPinTypeSPIu SPI工作模式配置的函數(shù):
- xSPIConfigSetl xSPIEnablel xSPIDisablel xSPIDMAEnablel xSPIDMADisableu
SSn管教狀態(tài)配置的函數(shù):
- xSPISSSetu 處理SPI中斷的APIs
- xSPIIntCallbackInitl xSPIIntEnable
- xSPIIntDisablel xSPIStatusGetu
獲取SPI工作狀態(tài)的APIs
- xSPIBitLengthGetl xSPIIsBusy
- xSPIIsRxEmptyl xSPIIsTxEmpty
- xSPIIsRxFulll xSPIIsTxFullu
處理SPI的數(shù)據(jù)讀寫的APIs
- xSPISingleDataReadWrite
- xSPIDataBufferRead
- xSPIDataBufferReadNonBlocking
- xSPIDataReadl xSPIDataBufferWrite
- xSPIDataBufferWriteNonBlocking
- xSPIDataWrite
2.2通用非強(qiáng)制接口
通用非強(qiáng)制接口是一類MCU通有的功能,而不是所有MCU都具有的功能接口:l xSPIErrorGetl xSPIErrorClear
2.3廠商庫(kù)特色接口
特色接口是包括了通用性接口,和MCU特有功能的接口。它并不是通用強(qiáng)制型或者通用非強(qiáng)制型,而是MCU特有的功能,就是在廠商庫(kù)特色接口這一組。相關(guān)的APIs接口如下:
- SPIAutoSSEnablel SPIAutoSSDisable
- SPISSClearl SPISSConfig
- SPILevelTriggerStatusGet
- SPIByteReorderSetl SPIVariableClockSet
- SPIDivOneFunction
- SPI3WireFunctionl SPI3WireAbort
- SPI3WireStartIntEnable
- SPI3WireStartIntDisable
- SPI3WireStartIntFlagGet
- SPI3WireStartIntFlagClear
另外廠商庫(kù)接口也實(shí)現(xiàn)了MCU其他所有的功能,比如:
SPIIntEnable(ulBase, ulIntFlags);
也實(shí)現(xiàn)了SPI中斷使能/失能模式的配置,這個(gè)在CoX接口的xSPIIntEnable也是這個(gè)功能。其實(shí)這個(gè)時(shí)候xSPIIntEnable的實(shí)現(xiàn)方式如下:
#define xSPIIntEnable(ulBase, ulIntFlags) \
SPIIntEnable(ulBase, ulIntFlags)
進(jìn)行了一次宏定義包裝罷了,對(duì)應(yīng)的參數(shù)也是進(jìn)行的一次宏定義比如:
//
//! End of transfer
//
#define xSPI_INT_EOT SPI_INT_EOT
3. 設(shè)計(jì)技巧簡(jiǎn)介
SPI模塊的CoX接口在設(shè)計(jì)的過程中非常注重“上層應(yīng)用簡(jiǎn)潔 下層驅(qū)動(dòng)通用”的核心思想, CoX.SPI組件提供了一套寄存器組件, 對(duì)所需要寫入寄存器的值進(jìn)行了宏定義,這樣使得用戶在操作過程中不需深究寄存器的細(xì)節(jié),使得配置更加直觀,同時(shí)也方便用戶調(diào)用寄存器接口定義自己的功能函數(shù)。下面以函數(shù)xSPIConfigSet(ulBase, ulBitRate, ulConfig)為例來說明:
比如將 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()函數(shù)的定義是 xSPIConfigSet(ulBase, ulBitRate, ulConfig) ,其中ulBase對(duì)應(yīng)SPIn的基地址,可以取值xSPI0_BASE、xSPI1_BASE、……,ulBitRate是SPI傳輸和接收數(shù)據(jù)的速率,ulConfig是SPI的各種工作狀態(tài)的組合。該函數(shù)的功能是非常豐富的,在執(zhí)行完該函數(shù)后,SPI就完成了傳輸速率、數(shù)據(jù)格式、工作狀態(tài)等配置。具體的實(shí)現(xiàn)過程如下:
#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控制寄存器中分別寫入數(shù)據(jù)格式、工作狀態(tài)、數(shù)據(jù)寬度等配置信息
(2)獲取SPI的系統(tǒng)時(shí)鐘,根據(jù)用戶設(shè)定的時(shí)鐘與獲取的SPI系統(tǒng)時(shí)鐘計(jì)算出分頻系數(shù)和分頻之后的值,然后將它們分別寫入對(duì)應(yīng)寄存器中。
(3)配置SSn管腳的觸發(fā)狀態(tài)。
在這個(gè)功能函數(shù)中我們集成了兩個(gè)函數(shù),其中SPIConfig(ulBase, ulBitRate, ulConfig)為廠商庫(kù)函數(shù),這個(gè)接口剛好可以給CoX接口調(diào)用,做好相應(yīng)的配置,不需要做特殊處理,這樣可以最大程度的重用代碼。同時(shí)為了方便用戶,CoX.SPI會(huì)在初始化時(shí)選取一些默認(rèn)狀態(tài)配置,例如SPISSConfig(ulBase, SPI_SS_LEVEL_TRIGGER, SPI_SS_ACTIVE_LOW_FALLING);這里默認(rèn)將SS腳配置成了低電平觸發(fā), 符合MCU大部分工作狀態(tài)下SS管腳的配置,這樣不僅可以減少用戶的工作量,也使得代碼更簡(jiǎn)潔,當(dāng)然用戶也可以使用CoX.SPI中的xSPISSSet()來自定義SS腳狀態(tài)。
CoX.SPI另一個(gè)主要特色就是引入了阻塞式和非阻塞式的概念.我們?cè)谠O(shè)計(jì)CoX.SPI接口的時(shí)候充分考慮實(shí)際編程的需求,相較于CoX1.0的數(shù)據(jù)處理,CoX2.0中特別增加了非阻塞式的數(shù)據(jù)發(fā)送和接收處理函數(shù),可以滿足不同情況下的SPI數(shù)據(jù)發(fā)送與接收。具體的函數(shù)名稱如下:
非阻塞式發(fā)送:xSPIDataBufferWriteNonBlocking ()
非阻塞式接收:xSPIDataBufferReadNonBlocking()
阻塞式發(fā)送:xSPIDataBufferWrite()
阻塞式接收:xSPIDataBufferRead()
比如在一些采用循環(huán)查詢SPI數(shù)據(jù)的系統(tǒng)中,MCU會(huì)不停的循環(huán)查詢SPI的數(shù)據(jù),這時(shí)如果我們采用一般的阻塞式的SPI數(shù)據(jù)接收,當(dāng)SPI沒有接收數(shù)據(jù)時(shí),MCU會(huì)一直停在這等待,不斷的查詢SPI數(shù)據(jù)接收情況,而無法執(zhí)行其他的任務(wù),這顯然不符合我們的要求,CoX1.0與廠商庫(kù)都不能很好的解決這一問題,而在CoX2.0中,由于我們引入了非阻塞式數(shù)據(jù)接收與處理的概念,這個(gè)時(shí)候我們就可以采用非阻塞式的數(shù)據(jù)接收處理,讓單片機(jī)在查詢SPI數(shù)據(jù)為空時(shí),可以繼續(xù)執(zhí)行下面的任務(wù),等待下次來再來查詢SPI數(shù)據(jù)狀態(tài),這樣就可以很好的解決等待SPI接收數(shù)據(jù)與運(yùn)行其它任務(wù)之間的矛盾問題。
4. SPI接口使用示例與移植
下面給出一個(gè)CoX.SPI的示例,都是使用的通用強(qiáng)制型的接口,因此下面的例子在所有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);
}
}
}
| 歡迎光臨 電子工程網(wǎng) (http://m.4huy16.com/) |
Powered by Discuz! X3.4 |