英创EM9280工控主板带有半双工的硬件SPI,与SPI协议的芯片通信时比使用GPIO模拟时序更加简单方便。本文以TLC2543芯片为例,介绍如何使用SPI获得芯片的AD数据。也为客户使用SPI驱动与其它型号芯片通信提供参考。
TLC2543芯片简介
TLC2543是德州仪器公司生产的12位开关电容型逐次逼近模数转换器,有11路AD输入。参考芯片手册资料,TLC2543支持8bit,12bit,16bit 的SPI协议,EM9280可以使用8bit和16bit的SPI与TLC2543通信。TLC2543是12位的AD,所以8bit会省略4位数据,而16bit会添加4位软件模拟数据。本文只介绍16bit的使用方法。
参考芯片数据手册。
上图为TLC2543 16bit的时序图,我们可以设置SPI为16bit,数据长度1字节来访问。
TLC2543发送数据定义,例如需要访问AIN6,即D7-D4为0110。读取数据采用单极性,MSB first,8bit,即D3-D0为0100。那么发送的1字节数据就为b0110 0100,即0x64。
因为EM9280的SPI为半双工,第一次16bit发送数据,第二次16bit读入数据。
资料说明TLC2543为12位AD。当使用16bit模式时会返回16位的数据,低4位为无效0。我们可以通过移位,处理为12位的数据
C#程序代码
参考EM9280光盘目录C# SPI例程,对照TLC2543芯片资料,修改相关参数设置。16bit本来应该使用short(2字节)数组进行操作,但是C#的Marshal.Copy只能操作byte数组,所以需要用byte数组来代替short数组,同时2位byte表示1位short。
比如:希望传送short[0] = 0x0c00;那么就设置byte[0] = 0x00;byte[1] = 0x0c;
同样在最后解析数据的时候,byte[0] = 0xc0;byte[1] = 0x6c;那么转换后便是short[0] = 0x6cc0;
先定义SPI为16bit,在SPI.cs中定义
private const int SSP_WORD_LENGTH_16BITS = 0xF;
在SPIConfigure函数中定义
spiinit.eLength = SSP_WORD_LENGTH_16BITS;
执行代码
…
//spi初始化代码---------------------------------
SPI.SPISetBandRate(hSPI, 2000000); //设置频率2MHz
//spi发送---------------------------------------
i = 0; //读取AIN0
//16bit
TxBuffer[0] = 0;
TxBuffer[1] = (byte)((i << 4) + 0x0c); //i左移4位到D7-D4,后面0x04为D3-D0
sSPI.BitCount = 16; //设置为16bit
sSPI.pDatBuf = pTxBuffer;
sSPI.dwDatLen = 1; //设置数据1字节
sSPI.bLockCS = 0; //0为发送
Marshal.Copy(TxBuffer, 0, pTxBuffer, 10);
bRes = SPI.WriteFile(hSPI, ref sSPI, sizeSPI, ref uLen, 0);
//spi接收---------------------------------------
sSPI.BitCount = 16;
sSPI.pDatBuf = pRxBuffer;
sSPI.dwDatLen = 10;
sSPI.bLockCS = 1;
bRes = SPI.ReadFile(hSPI, ref sSPI, sizeSPI, ref uLen, 0);
Marshal.Copy(pRxBuffer, RxBuffer, 0, 10);
int AIN = RxBuffer[0] + RxBuffer[1]*256; //读得数据
测试结果
AIN = AIN / 16; //右移4位,舍弃后4位软件模拟数据
Double dAIN = (double)AIN / 4096.0 * 4.86;
这里读得AIN为0x6cc0,右移动4位为0x06cc,为12位AD数据,所以除以2^12即4096,再乘上基准电压(用万用表测得4.86V),结果为2.064V,用万用表量得结果,几乎是一样的。
C程序代码
参考EM9280光盘目录C SPI例程,对照TLC2543芯片资料,修改相关参数设置。
先定义SPI为16bit
#define UseBitCount16 1 //修改该定义为或,实现位数据位或位数据位通讯
#if UseBitCount16
#define dBitCount 16
#else
#define dBitCount 8
#endif
定义BUFFER为16字节数组
WORD SPI_TxBuf[10],SPI_RxBuf[10];
执行代码
…
//spi初始化代码---------------------------------
SPISetBandRate( hSPI , 2000000); //设置频率2MHz
//spi发送---------------------------------------
i = 0; //读取AIN0
SPI_TxBuf[0]= ((i << 4) + 0x0c)<<8; //i左移位到D7-D4,后面x0c为D3-D0,最后要左移8位,因为协议里16位前8位有效
hSPI_Box.BitCount = dBitCount; //设置为8bit
hSPI_Box.bLockCS = 0; //0为发送
hSPI_Box.dwDatLen = 1; //设置数据1字节
hSPI_Box.pDatBuf = (BYTE*)SPI_TxBuf;
WriteFile( hSPI , &hSPI_Box , sizeof( hSPI_Box ) , (DWORD*)&i , 0 );
//spi接收---------------------------------------
hSPI_Box.bLockCS = 1;
hSPI_Box.dwDatLen = 1;
hSPI_Box.pDatBuf = (BYTE*)SPI_RxBuf;
ReadFile( hSPI , &hSPI_Box , sizeof( hSPI_Box ) , (DWORD*)&i , 0 );
测试结果
f=(double)(SPI_RxBuf[0]>>4)/4096.0*4.86 ;
这里读得SPI_RxBuf[0]为0x6ca0,右移动4位为0x06ca,为12位AD数据,所以除以2^12即4096,再乘上基准电压(用万用表测得4.86V),结果为2.062V,用万用表量得结果,几乎是一样的。
详细SPI例程代码见光盘SPI例程,相关问题,客户可以联系英创工程师咨询。
全部0条评论
快来发表一下你的评论吧 !