【RT1020】- SPI Polling 连续发送两次出现失败的问题解决

一、前言

在使用 SDK 的 SPI 例程的时候,偶然发现在多次发送单个字节的情况下,会出现只发了一个字节的情况。详情看下面代码。

static uint8_t TxData=0x45;
static uint8_t rxData=0;
masterXfer.txData = (uint8_t *)(&TxData);
masterXfer.rxData = (uint8_t *)(&rxData);
masterXfer.dataSize = 1;
masterXfer.configFlags =
EXAMPLE_LPSPI_MASTER_PCS_FOR_TRANSFER | kLPSPI_MasterPcsContinuous | kLPSPI_MasterByteSwap;

LPSPI_MasterTransferBlocking(EXAMPLE_LPSPI_MASTER_BASEADDR, &masterXfer);

masterXfer.txData = (uint8_t *)(&TxData);
masterXfer.rxData = (uint8_t *)(&rxData);
masterXfer.dataSize = 1;
masterXfer.configFlags =
EXAMPLE_LPSPI_MASTER_PCS_FOR_TRANSFER | kLPSPI_MasterPcsContinuous | kLPSPI_MasterByteSwap;

LPSPI_MasterTransferBlocking(EXAMPLE_LPSPI_MASTER_BASEADDR, &masterXfer);

每一次发送都只发一个字节,发两次,然后这个过程每 20ms 重复一次,然后抓到的 SPI 波形就如下图。

每次都只出来第一个 0x45,后面那个就没发出来

然后简单修改一下代码

这样就两个 0x45 都出来了,这样看似解决了问题,但是貌似这个 API 就不好用了。

二、解析

通常在使用 SPI 配置某些传感器或者设备的时候,指令会是一个 Byte,然后还要从从机那里接收回应,看看有没有写入成功,如果我们直接把接收数据的指针直接改为空,那就不知道是不是配置成功了。

进入发送函数的底层。

LPSPI_MasterTransferBlocking(EXAMPLE_LPSPI_MASTER_BASEADDR, &masterXfer);

可以看到在最后有一个判断。

  /*Read out the RX data in FIFO*/
if (rxData != NULL)
{
while (rxRemainingByteCount > 0U)
{
#if SPI_RETRY_TIMES
waitTimes = SPI_RETRY_TIMES;
while ((LPSPI_GetRxFifoCount(base) != 0U) && (--waitTimes != 0U))

#else
while (LPSPI_GetRxFifoCount(base) != 0U)
#endif
{
readData = LPSPI_ReadData(base);

if (rxRemainingByteCount < bytesEachRead)
{
bytesEachRead = (uint8_t)rxRemainingByteCount;
}

LPSPI_SeparateReadData(rxData, readData, bytesEachRead, isByteSwap);
rxData += bytesEachRead;

rxRemainingByteCount -= bytesEachRead;
}
#if SPI_RETRY_TIMES
if (waitTimes == 0U)
{
return kStatus_LPSPI_Timeout;
}
#endif
}

}
else
{
/* If no RX buffer, then transfer is not complete until transfer complete flag sets */
#if SPI_RETRY_TIMES
waitTimes = SPI_RETRY_TIMES;
while (((LPSPI_GetStatusFlags(base) & (uint32_t)kLPSPI_TransferCompleteFlag) == 0U) && (--waitTimes != 0U))
#else
while ((LPSPI_GetStatusFlags(base) & (uint32_t)kLPSPI_TransferCompleteFlag) == 0U)
#endif
{
}
#if SPI_RETRY_TIMES
if (waitTimes == 0U)
{
return kStatus_LPSPI_Timeout;
}
#endif
}

可以看到在最后有一个判断,如果接收数据的指针不为空,就从 FIFO 里面读取数据,然后就完成这次的通信过程,如果是空的,就是说这次是单发不接收,那就等待发送完成标志置位,然后结束这次通信过程。有没有觉得少了什么。

就是接收指针不为空的时候,并没有等待发送完成的这个过程,也就是说这次过程直接就结束了,不知道有没有发送完成。

所以问题出在这里,需要在这里补上,等待发送完成的过程,等发完了才能退出,返回 success,不是直接退出。

这个时候,就算接收指针不为空,也可以正确地发出去数据了。如下图所示。

三、总结

本文总结了一个 RT1020 SPI 阻塞发送,发送不正常问题的解决过程。

四、参考资料
1、NXP  SDK(可自行到官网下载)

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论