概述
本文通过分析SPI主从通讯的特点,总结出一套访问从设备的一般化方法。
了解更多SPI可访问S32K1专栏:
NXP S32K1 SPI模块
NXP S32K1 SPI模块Driver使用
SPI时钟极性、相位设置
SPI实例之C++实现EEPROM访问
常见的SPI从设备有EEPROM、FLASH、收发器、转换器、通讯模块等,在片选信号有效后,在主机时钟线的驱使下,主机输出数据或者主机接收至从机。
Master Write
对于主机输出数据,亦从机接收数据(配置从机、写数据到从机的场景),主机需指明写数据到从机的哪里(地址、寄存器),写入的数据,甚至在“地址”区域需要搭配命令来指明这是一个写操作,或者像IIC一样,通过LSB的两种状态来指定操作。
Master Read
对于主机接收数据,亦从机输出数据,主机在本次通讯六中指明在从机的哪里(地址)去读取数据,只有主机告诉从机了这个地址,从机协议解析(处理器)模块才能将该位置的数据通过SPI数据流的方式输出。
一般化
由此从主机角度来看,SPI通讯流(字节流)有两部分组成:hdr+buff。
hdr: 头部,可能是Cmd和/或Reg+Addr,其割断的长度在不同的从机中也各不相同,可能是1Byte,也可能是2Bytes。
buff:数据缓冲区,rxBuf和txBuf,即使在主机输出数据的情况下,从机同样会移位输出输出到从机的接受线,反之亦然。
示例代码
bool EEPROM::ReadBytes(uint16_t addr, uint8_t *data, uint16_t len)
{
bool rtv = false;
if(data && (len>0))
{
uint8_t *pTx = new uint8_t[len+EE_LEN_HDR];
uint8_t *pRx = new uint8_t[len+EE_LEN_HDR];
if(pTx && pRx)
{
*(pTx+0) = EE_CMD_READ;
*(pTx+1) = EE_GET_ADD_H(addr);
*(pTx+2) = EE_GET_ADD_L(addr);
if(STATUS_SUCCESS == LPSPI_DRV_MasterTransferBlocking(EE_SPI, pTx, pRx, len+EE_LEN_HDR, EE_TIME_OUT))
{
memcpy((uint8_t*)data,(uint8_t*)(pRx+EE_LEN_HDR),len);
rtv = true;
}
else
{
rtv = false;
}
}
else
{
rtv = false;
}
delete pTx;pTx = NULL;
delete pRx;pRx = NULL;
}
return rtv;
}
结语
了解更多SPI可访问S32K1专栏:
NXP S32K1 SPI模块
NXP S32K1 SPI模块Driver使用
SPI时钟极性、相位设置
SPI实例之C++实现EEPROM访问