因为SPI+阻塞方式可以使得字节间有大约0.4us的间隔(示波器查看得出),可适应从设备的数据准备时间,故用来做数据读取;
但此种方法对于向从设备写入大量数据来说,所需时间较长,比如写1700字节大约需要1.3ms左右。该时间超出RTOS的节拍,担心因此引入中断打断传输,或使用临界区保护又会干扰其他任务的实时调度。于是采用SPI+DMA的方式,实测1700字节写入大约需要0.68ms左右。
于是同一个系统中存在两种SPI使用方式:“SPI+阻塞(循环等待寄存器变化)”以及“SPI+DMA”;调试过程中也遇到了不少问题:
1、SPI+DMA只发送了一次就不发了。查看是因为没有打开SPI中断,未调用HAL库的SPI IRQhander来恢复hspi1.state为“ready”状态。因为使用HAL_SPI_Transmit_DMA()会将hspi1.state置为“BUSY”;
2、打开SPI中断,使中断处理程序调用SPI IRQhander来恢复hspi1.state为“ready”状态。但又出现在“SPI+阻塞“中一直卡在等待SPI RXNE为1好返回DR值上(此时SPI RXNE确实一直为0)。猜想可能是中断处理程序调用SPI IRQhander在中断中清除了RXNE或者其他操作影响了RXNE(时间所限,未经证实!);
3、取消SPI中断,自己强制将hspi1.state置为“ready”状态,可以跑了,但持续发送数据时卡顿,且用“SPI+阻塞“读取的数据也会周期性出错!加上SPI取消TXDMAEN位也不起作用;
4、搜了下看到有人说需要用HAL_SPI_Abort(),试了下果然可以,顺畅不卡顿。而且该函数会处理hspi1.state置为“ready”状态,以及取消TXDMAEN,所以可以不用自己处理了。但会禁用SPI,如果后续代码还要使用SPI,则需要自己再启用。
void Write_DataDMA(uint32_t Addr, uint8_t* pBuf, uint16_t len)
{
HAL_GPIO_WritePin(W5100S_SCS_GPIO_Port, W5100S_SCS