在基于工控主板EM9160的嵌入式應(yīng)用中,經(jīng)常需要與具有SPI接口的芯片或電路單元,進行數(shù)據(jù)通訊。通常情況下,我們建議采用基于GPIO的SPI通訊協(xié)議實現(xiàn)方案,其優(yōu)點是靈活性,客戶可使用任意的GPIO管腳來實現(xiàn)SPI通訊,有關(guān)這方面的技術(shù)方案的實現(xiàn),可參考英創(chuàng)網(wǎng)站的《使用GPIO控制SPI接口的AD芯片》一文。在SPI通訊中,還有一類應(yīng)用需要進行大數(shù)據(jù)量的傳輸,且要求盡可能高的波特率,這時若采用基于GPIO的方案,就可能造成占用過多的CPU資源。因此需要使用EM9160的硬件SPI接口。
EM9160的硬件SPI接口為4線制SPI,其管腳與GPIO12–GPIO15復用:
GPIO管腳 | SPI接口信號 | 簡要說明 |
GPIO12 | SPI_DIN | 串行數(shù)據(jù)輸入 |
GPIO13 | SPI_DOUT | 串行數(shù)據(jù)輸出 |
GPIO14 | SPI_CLK | 串行數(shù)據(jù)同步時鐘輸出 |
GPIO15 | SPI_CS# | 片選控制輸出,低電平有效 |
為了操作硬件SPI接口,應(yīng)用程序需要打開“SPI1:”的設(shè)備文件:
HANDLEhDevice;
hDevice = CreateFile( _T('SPI1:'),
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
return -1;
}
獲得有效的文件句柄后,就可通過DeviceIoControl(…)函數(shù)來操作SPI接口了。在EM9160的SDK中已封裝了相應(yīng)的API函數(shù),以方便應(yīng)用程序的使用。相關(guān)的數(shù)據(jù)結(jié)構(gòu)和函數(shù)定義,包括在“SPI_API.h”中:
// 定義SPI通訊參數(shù)結(jié)構(gòu)
typedef struct
{
DWORD dwCLKPolarity; // SPI時鐘極性:=0 或者 =1
DWORD dwCLKPhase; // SPI時鐘相位:=0 或者 =1
DWORD dwDataBitSize; // SPI通訊數(shù)據(jù)幀的位數(shù):8bit-16bit
DWORD dwBaudRate; // SPI通訊波特率:最高波特率為10Mbps
} SPISTATE;
盡管EM9160的硬件波特率可以高達100Mbps,但為了保證可靠傳輸,建議應(yīng)用程序把波特率控制在10Mbps以下。SPI時鐘極性dwCLKPolarity,在數(shù)據(jù)手冊中通常記為CPOL,= 0表示在沒有數(shù)據(jù)傳輸時為低電平,= 1表示沒有數(shù)據(jù)傳輸時為高電平。SPI時鐘相位dwCLKPhase,在數(shù)據(jù)手冊中通常記為CPHA,= 0表示時鐘的第一個沿更新數(shù)據(jù)、第二個沿鎖存數(shù)據(jù),= 1表示時鐘的第一個沿鎖存數(shù)據(jù)、第二個沿更新數(shù)據(jù)。下面的事宜圖,以8-bit數(shù)據(jù)為例:
CPHA = 0的SPI時序
CPHA = 1的SPI時序
SPI通訊參數(shù)設(shè)置,通過以下兩個函數(shù)實現(xiàn):
// 功能描述:設(shè)置SPI通訊參數(shù)。
// 輸入?yún)?shù) HANDLE hDevice: 運行CreateFile( _T('SPI1:'),....)函數(shù)返回的有效句柄
// SPISTATE *pSPIState: SPI通訊參數(shù)
// 返回值 = TRUE: SPI通訊參數(shù)成功。
// = FALSE: SPI通訊參數(shù)失敗。
BOOL SetSPIState( HANDLE hDevice, SPISTATE *pSPIState );
// 功能描述:獲取SPI通訊參數(shù)。
// 輸入?yún)?shù) HANDLE hDevice: 運行CreateFile( _T('SPI1:'),....)函數(shù)返回的有效句柄
// 輸出 SPISTATE *pSPIState: 獲取的SPI通訊參數(shù)
// 返回值 = TRUE: SPI通訊參數(shù)成功。
// = FALSE: SPI通訊參數(shù)失敗。
BOOL GetSPIState( HANDLE hDevice, SPISTATE *pSPIState );
在調(diào)用上述函數(shù)時,注意指針pSPIState需要初始化分配空間。在設(shè)置好SPI參數(shù)后,就可調(diào)用下面的函數(shù)進行具體的數(shù)據(jù)通訊了
// 功能描述:全雙工收發(fā)SPI數(shù)據(jù)
// 輸入?yún)?shù):
// HANDLE hDevice: 運行CreateFile( _T('SPI1:'),....)函數(shù)返回的有效句柄
// DWORD DatLength: 需收發(fā)的數(shù)據(jù)樣點長度, (DatLength * 字節(jié)數(shù)/樣點) < 1024。
// PVOID pTxBuf: 需發(fā)送的數(shù)據(jù)BUFFER,注意一個數(shù)據(jù)樣點可能占用2個字節(jié)。
// PVOID pRxBuf: 需接收的數(shù)據(jù)BUFFER,注意一個數(shù)據(jù)樣點可能占用2個字節(jié)。
// 返回值 = TRUE: SPI數(shù)據(jù)通訊成功。
// = FALSE: SPI數(shù)據(jù)通訊失敗。
BOOL SPI_FullDuplex( HANDLE hDevice,
PVOID pTxBuf,
PVOID pRxBuf,
DWORD DatLength );
在調(diào)用上述SPI函數(shù),需要注意以下事宜:
1、SPI設(shè)備驅(qū)動程序的內(nèi)部buffer缺省設(shè)置為1K字節(jié),因此每次通訊的字節(jié)數(shù)不能超過1K字節(jié),對大于8-bit的數(shù)據(jù),每個數(shù)據(jù)均按2個字節(jié)計算。
2、對8-bit的SPI傳輸,收發(fā)數(shù)據(jù)buffer的類型應(yīng)設(shè)置為UCHAR;而對9-bit – 16-bit的數(shù)據(jù)傳輸,其收發(fā)數(shù)據(jù)buffer的類型應(yīng)設(shè)置為WORD。
3、參數(shù)DatLength是以數(shù)據(jù)為單位計算的,所以若傳輸8-bit數(shù)據(jù),其最大值為1024,若傳輸8-bit以上數(shù)據(jù),其最大值為512。
4、對傳輸長度超過SPI設(shè)備驅(qū)動程序的內(nèi)部buffer長度的應(yīng)用,可通過循環(huán)多次調(diào)用來實現(xiàn)數(shù)據(jù)通訊。
-
嵌入式主板
+關(guān)注
關(guān)注
7文章
6085瀏覽量
35402
發(fā)布評論請先 登錄
相關(guān)推薦
評論