<strike id="kiyse"></strike>
  • <tr id="kiyse"></tr>
  • <strike id="kiyse"></strike><samp id="kiyse"><tbody id="kiyse"></tbody></samp>
    <strike id="kiyse"><s id="kiyse"></s></strike>
    <tr id="kiyse"></tr>
    <noframes id="kiyse"><code id="kiyse"></code></noframes>
    <th id="kiyse"></th>
    <samp id="kiyse"></samp>
  • <th id="kiyse"><s id="kiyse"></s></th>
  • EM9280系列SPI接口應用方案

     2014-7-28             

      EM9280系列產品包括EM9280、EM9287和EM9281,是英創公司新一代的低成本嵌入式主板產品。該主板的SPI接口,在內部DMA(Direct Memory Access直接內存存取)機制的驅動下,其最高數據傳輸速度可達20Mbps。另外SPI接口可支持4bit、8bit、16bit位長的數據通訊;也可對SPI時序的極性及相位進行設置。

     

      針對SPI接口的應用特點,EM9280的SPI的驅動進行了專門的優化,不僅可支持常規的SPI讀、寫操作,還可支持外部中斷觸發的讀寫操作。中斷觸發的讀寫操作,主要應用于工業控制的高速數據采集。另一方面,針對AD芯片控制需求,SPI驅動還支持混合讀寫模式的數據傳輸操作。

     

      本文以下部分重點介紹SPI驅動API的使用方法。

     

    操作SPI設備的基本步驟

     

      1、打開SPI設備文件,其設備文件名為“SPI1:”
      2、根據應用需求,設置SPI數據幀的基本參數,包括數據長度、波特率、時鐘極性等參數。
      3、若需要用到外部中斷觸發SPI讀取操作,則需要設置外部GPIO中斷管腳,及中斷后的讀取數據的長度。
      4、設置完成后,對常規操作,即可使用標準的ReadFile函數接收SPI數據、使用WriteFile發送SPI數據。
      5、對需要讀寫混合操作的,則需要調用DeviceIoControl來實現。
      6、當啟動了外部中斷,則通過調用DeviceIoControl來等待外部事件,然后再調用ReadFile函數來讀取已緩沖在驅動程序內部的SPI數據。
      7、調用CloseHandle將關閉SPI接口并清除相關設置。即使重新打開SPI設備文件,需重新設置SPI的參數,才能進行讀寫。

     

    SPI數據幀參數設置

     

      初始化SPI,需要用到下面這個數據結構:
      typedef struct _SPIFrame
      {
        UCHAR ucBitLength; // SPI數據bit長度,= 4、8、16
        DWORD dwBitRate; // SPI波特率,20000000對應20Mbps
        BOOL bPhase; // 時鐘相位
        BOOL bPolarity; // 時鐘極性
      } SPIFrame , *PSPIFrame;

     

      該數據結構在hw_spi.h頭文件中進行的定義,數據結構中的變量說明:
      ucBitLength:SPI通訊的數據位長,EM9280/EM9287支持4bit、8bit、16bit三種數據位長格式,在hw_spi.h中定義了這三種數據位長的常量。
      dwBitRate:SPI時鐘速率,為每秒傳輸的bit數,參數20000000表示20Mbps,
      bPhase:SPI時序相位設置(如下圖所示)
      bPolarity:SPI時序極性設置(如下圖所示)

     

    bPhase=0 , bPolarity=0

     

    bPhase=1 , bPolarity=0

     

    bPhase=0 , bPolarity=1

     

    bPhase=1 , bPolarity=1

     

    SPI設備的初始化例子

     

      HANDLE hSPI;
      SPIFrame ConfigSPI;

      // 打開設備驅動文件
      hSPI = CreateFile(L”SPI1:”, // name of device
        GENERIC_READ|GENERIC_WRITE, // desired access
        FILE_SHARE_READ|FILE_SHARE_WRITE, // sharing mode
        NULL, // security attributes (ignored)
        OPEN_EXISTING, // creation disposition
        FILE_FLAG_RANDOM_ACCESS, // flags/attributes
        NULL); // template file (ignored)

      if(hSPI == FALSE )
      {
        printf('SPI Open False!!!\r\n');
        return 0;
      }

      // 配置SPI參數
      ConfigSPI.ucBitLength=SSP_WORD_LENGTH_8BITS; // Len_8BITS
      ConfigSPI.dwBitRate=10000000; // 10Mbps
      ConfigSPI.bPhase=0;
      ConfigSPI.bPolarity=0;
      DeviceIoControl(hSPI, // file handle to the driver
        SPI_IOCTL_SSPCONFIGURE, // I/O control code
        &ConfigSPI, // in buffer
        sizeof(ConfigSPI), // in buffer size
        NULL,
        0,
        NULL,
        NULL)

     

    SPI接口的單向讀寫操作

     

      用標準的ReadFile和WriteFile就可實現常規的SPI數據接收(讀)或發送(寫)。

     

      SPI數據接收的函數調用:
      ReadFile(hSPI, // 設備驅動文件句柄
      pDatBuf, // 數據buffer指針,注意指針類型!
      dwBufLength, // 數據buffer的字節長度
      pdwBytesRead, // 實際讀取的SPI數據字節數
      NULL)

     

      pDatBuf:數據BUFF指針。需要注意的是SPI數據幀長度若為4-bit或8-bit,則每個SPI數據占用一個字節,而對16-bit的SPI數據,則占用2個字節。一般來說,對4-bit或8-bit的SPI傳輸,其數據buffer應當是BYTE類型的;對16-bit的SPI傳輸,數據buffer則為WORD類型的。

      dwBufLength:需要傳輸的數據字節長度。該參數是以字節為單位,其涵義也與SPI數據長度有關,對16-bit的SPI傳輸,dwBufLength應為2的倍數。

      pdwBytesRead:SPI數據實際接收的字節數。一個正確的SPI數據接收調用后,指針pdwByteRead所包含的數據應等于dwBufLength,才能表示SPI數據接收執行完全正確。

     

      SPI數據發送的函數調用:
      WriteFile(hSPI, // 設備驅動文件句柄
      pDatBuf, // 數據buffer指針,事先應把數據填入
      dwBufLength, // 數據buffer的字節長度
      pdwBytesWritten, // 實際發送的SPI數據字節數
      NULL)

     

      發送函數的參數定義與接收函數的參數定義是一致的。特別的,一個正確的SPI數據發送調用后,指針pdwByteWritten所包含的數據應等于dwBufLength。

     

    讀寫混合型的SPI操作

     

      在SPI的實際應用,有時需要在一個連續的片選過程中,既有讀操作,也有寫操作。這時間需要用到所謂的混合型SPI操作。

     

      混合型SPI操作需要用到以下數據結構:
      typedef struct _SPITransfer
      {
        LPVOID pTxBuff; // SPI發送buffer指針
        LPVOID pRxBuff; // SPI接收buffer指針
        DWORD dwBufLength; // 本次SPI傳輸的字節數
      } SPITransfer;

     

      pTxBuff:SPI輸出數據BUFF指針
      pRxBuff:SPI讀入數據BUFF指針
      dwBufLength:SPI數據傳輸長度,以字節為單位

     

      注意,EM9280的SPI接口僅支持半雙工操作,因此在上述結構中,只能有一個buffer指針為有效指針,另一個必須為NULL。dwBufLength的定義與單向讀寫的定義一致。具體的傳輸是通過DeviceIoControl來實現的,舉例說明,本例首先進行發送1個字節(8-bit SPI),然后接收2個字節。

     

      SPITransfer Trans[2];
      BYTE Tx[16], Rx[16]; // buffer足夠大

      Tx[0] = 0xE5; // 發送的字節
      Trans[0].pTxBuf = Tx;
      Trans[0].pRxBuf = NULL;
      Trans[0].dwBufLength = 1; // 要發送1字節
      Trans[1].pTxBuf = NULL;
      Trans[1].pRxBuf = Rx;
      Trans[1].dwBufLength = 2; // 要接收2字節

      DeviceIoControl(hSPI,
        SPI_IOCTL_EXCHANGE,
        Trans, // in buffer
        sizeof(Trans) , // in buffer size
        NULL,
        0,
        NULL,
        NULL))

     

      在上述調用中需要注意的是,DeviceIoControl()輸入參數中的buffer長度必須是數據結構SPITransfer大小的整倍數,否則將被視作無效參數。

     

    外部中斷觸發的SPI操作

     

      外部中斷觸發的SPI操作,主要是利用SPI的高速特性,進行實時的大數據量讀取。因為SPI的接線非常簡單,作為一種高效低成本的接口模式在工業控制領域有廣泛的應用。使用這種SPI操作方式,需要用到以下數據結構:
      typedef struct _SPI_IrqTransfer
      {
        DWORD dwGpioPin; // 外部中斷管腳,上升沿觸發中斷
        DWORD dwBufLength; // 中斷觸發的SPI傳輸的字節數,小于64KB
        DWORD dwRVSD; // 保留,必須設置為0
      } SPI_IrqTransfer;

     

      dwGpioPin:要用作外部中斷源的GPIO引腳
      dwBufLength:要讀取的數據字節長度
      dwRVSD:系統保留,必須設置為0

     

      在上述結構中,dwBufLength的定義與單向讀寫的定義一致,如果dwGpioPin與dwBufLength同時設置為0,則將關閉已打開的GPIO中斷資源并禁止該功能啟動。dwGpioPin為EM9280主板的GPIO引腳編號,與GPIO操作時的引腳數據一致。注意:由于系統功能的占用,不是所有的GPIO引腳都可以用作外部中斷觸發源。

     

      ? EM9280可以使用的GPIO引腳有:GPIO0、GPIO1、GPIO6、GPIO7、GPIO10、GPIO11、GPIO20、GPIO21、GPIO22、GPIO23。

      ? EM9287和EM9281可以使用的GPIO引腳有:GPIO0 - GPIO23。

     

      該操作的具體的設置操作仍然需要調用DeviceIoControl()來實現。
      SPI_IrqTransfer irq_transfer;
      irq_transfer. dwGpioPin=GPIO0; // 使用GPIO0作為SPI的外部中斷源
      irq_transfer. dwBufLength=1024; // 中斷產生后需要讀取1024字節的數據
      irq_transfer. dwRVSD=0;
      DeviceIoControl(hSPI,
        SPI_IOCTL_SSP_IRQTransfer,
        & irq_transfer, // 輸入參數
        sizeof(SPI_IrqTransfer), // 輸入參數字節數
        NULL,
        0,
        NULL,
        NULL);

     

      設置完成即啟動外部中斷自動觸發SPI操作,一旦中斷產生,驅動程序將自動接收dwBufLength長度的數據,存儲在驅動程序的內部緩沖區中。數據接收完成后,將發送事件通知應用層。應用程序可通過DeviceIoControl()調用來等待該事件,得到事件后再調用ReadFile讀取數據。通過調用DeviceIOControl()等待SPI事件,可以給定一個時間參數作為等待超時的條件,以ms為單位。成功等到SPI執行完成的消息時,DeviceIoControl會返回TRUE,否則返回FALSE。SPI事件等待的調用方法如下:
      DeviceIoControl(hSPI,
        SPI_IOCTL_SSP_WaitSPIEvent,
        &DelayTime, // 等待超時,時間為ms
        Sizeof(DWORD),
        NULL,
        0,
        NULL,
        NULL)

     

      調用上述方法啟動了外部中斷觸發SPI讀取數據的功能后,該功能將一直存在,即每次在所設置的GPIO引腳上產生中斷信號,都會執行一次SPI讀取操作,直到應用程序關閉該中斷,即設置dwGpioPin和dwBufLength等于0,再調用DeviceIoControl()進行設置操作。

     

      SPI操作相關的范例代碼請參考光盤中的EM9280_SPIDemo,或來郵件索取或咨詢。

    日本精品VIDEOSSE×少妇| 久久精品国产亚洲av麻豆 | 精品国产男人的天堂久久| 成人午夜视频精品一区| 牛牛本精品99久久精品| 91久久精品国产91久久性色也| 国产精品综合专区中文字幕免费播放 | 人妻互换精品一区二区| 午夜精品射精入后重之免费观看| 国产乱人伦偷精品视频不卡| 嫩草影院精品视频在线观看| 亚洲精品国产情侣av在线| 国产精品拍天天在线| 久久精品99无色码中文字幕| 国产在线无码精品无码| 亚洲精品国产第一综合99久久| 亚洲精品偷拍无码不卡av| 国产精品高清一区二区三区| 精品无人区无码乱码毛片国产| 国产嫩草影院精品免费网址 | 午夜精品福利影院| 国产精品视频免费| 91精品国产自产在线观看永久∴| 国产产无码乱码精品久久鸭| 国产成人精品午夜二三区波多野| 日本一区二区三区精品国产 | 国产亚洲精品看片在线观看| 国产精品成人精品久久久| 国产精品免费看久久久无码| 麻豆精品国产免费观看| 国产一精品一AV一免费孕妇| 2021国产精品成人免费视频| 亚洲精品视频在线观看视频| 99久久99久久精品| 蜜桃麻豆WWW久久囤产精品| 3d动漫精品成人一区二区三| 精品人妻中文字幕有码在线| 亚洲精品高清国产一久久| 午夜精品乱人伦小说区| 久久精品中文无码资源站| 久久精品中文无码资源站 |