技术天地

工控主板EM9160硬件SPI接口的应用    发布时间:2010-7-12    被阅览数:

  在基于工控主板EM9160的嵌入式应用中,经常需要与具有SPI接口的芯片或电路单元,进行数据通讯。通常情况下,我们建议采用基于GPIO的SPI通讯协议实现方案,其优点是灵活性,客户可使用任意的GPIO管脚来实现SPI通讯,有关这方面的技术方案的实现,可参考英创网站的《使用GPIO控制SPI接口的AD芯片》一文。在SPI通讯中,还有一类应用需要进行大数据量的传输,且要求尽可能高的波特率,这时若采用基于GPIO的方案,就可能造成占用过多的CPU资源。因此需要使用EM9160的硬件SPI接口。

  EM9160的硬件SPI接口为4线制SPI,其管脚与GPIO12–GPIO15复用:


GPIO管脚

SPI接口信号

简要说明

GPIO12

  SPI_DIN  串行数据输入

GPIO13

  SPI_DOUT  串行数据输出

GPIO14

  SPI_CLK  串行数据同步时钟输出

GPIO15

  SPI_CS#  片选控制输出,低电平有效


 

  为了操作硬件SPI接口,应用程序需要打开“SPI1:”的设备文件:

  HANDLE hDevice;
  hDevice = CreateFile( _T('SPI1:'),
            GENERIC_READ | GENERIC_WRITE,
            0, NULL, OPEN_EXISTING, 0, NULL);
  if (hDevice == INVALID_HANDLE_VALUE)
  {
    return -1;
  }

  获得有效的文件句柄后,就可通过DeviceIoControl(…)函数来操作SPI接口了。在EM9160的SDK中已封装了相应的API函数,以方便应用程序的使用。相关的数据结构和函数定义,包括在“SPI_API.h”中:

  // 定义SPI通讯参数结构
  typedef struct
  {
    DWORD   dwCLKPolarity;    // SPI时钟极性:=0 或者 =1
    DWORD   dwCLKPhase;     // SPI时钟相位:=0 或者 =1
    DWORD    dwDataBitSize;    // SPI通讯数据帧的位数:8bit-16bit
    DWORD   dwBaudRate;     // SPI通讯波特率:最高波特率为10Mbps
  } SPISTATE;

  尽管EM9160的硬件波特率可以高达100Mbps,但为了保证可靠传输,建议应用程序把波特率控制在10Mbps以下。SPI时钟极性dwCLKPolarity,在数据手册中通常记为CPOL,= 0表示在没有数据传输时为低电平,= 1表示没有数据传输时为高电平。SPI时钟相位dwCLKPhase,在数据手册中通常记为CPHA,= 0表示时钟的第一个沿更新数据、第二个沿锁存数据,= 1表示时钟的第一个沿锁存数据、第二个沿更新数据。下面的事宜图,以8-bit数据为例:

  CPHA = 0的SPI时序


  CPHA = 1的SPI时序


  SPI通讯参数设置,通过以下两个函数实现:

  // 功能描述:设置SPI通讯参数。
  // 输入参数 HANDLE hDevice: 运行CreateFile( _T('SPI1:'),....)函数返回的有效句柄
  //          SPISTATE *pSPIState: SPI通讯参数
  // 返回值 = TRUE:  SPI通讯参数成功。
  //        = FALSE: SPI通讯参数失败。
  BOOL SetSPIState( HANDLE hDevice, SPISTATE *pSPIState );

  // 功能描述:获取SPI通讯参数。
  // 输入参数 HANDLE hDevice: 运行CreateFile( _T('SPI1:'),....)函数返回的有效句柄
  // 输出     SPISTATE *pSPIState: 获取的SPI通讯参数
  // 返回值 = TRUE:  SPI通讯参数成功。
  //        = FALSE: SPI通讯参数失败。
  BOOL GetSPIState( HANDLE hDevice, SPISTATE *pSPIState );

  在调用上述函数时,注意指针pSPIState需要初始化分配空间。在设置好SPI参数后,就可调用下面的函数进行具体的数据通讯了

  // 功能描述:全双工收发SPI数据
  // 输入参数:
  // HANDLE hDevice: 运行CreateFile( _T('SPI1:'),....)函数返回的有效句柄
  // DWORD DatLength: 需收发的数据样点长度, (DatLength * 字节数/样点) < 1024。
  // PVOID pTxBuf:     需发送的数据BUFFER,注意一个数据样点可能占用2个字节。
  // PVOID pRxBuf:     需接收的数据BUFFER,注意一个数据样点可能占用2个字节。
  // 返回值 = TRUE:  SPI数据通讯成功。
  //        = FALSE: SPI数据通讯失败。
  BOOL SPI_FullDuplex( HANDLE hDevice,
             PVOID pTxBuf,
             PVOID pRxBuf,
             DWORD DatLength );

  在调用上述SPI函数,需要注意以下事宜:

  1、SPI设备驱动程序的内部buffer缺省设置为1K字节,因此每次通讯的字节数不能超过1K字节,对大于8-bit的数据,每个数据均按2个字节计算。
  2、对8-bit的SPI传输,收发数据buffer的类型应设置为UCHAR;而对9-bit – 16-bit的数据传输,其收发数据buffer的类型应设置为WORD。
  3、参数DatLength是以数据为单位计算的,所以若传输8-bit数据,其最大值为1024,若传输8-bit以上数据,其最大值为512。
  4、对传输长度超过SPI设备驱动程序的内部buffer长度的应用,可通过循环多次调用来实现数据通讯。


Go Top