之前使用SPI,主机模式下,全双工通信,外接了一个片外FLASH,波特率还挺高的,使用的是阻塞的发送:HAL_SPI_TransmitReceive(对了,HAL库实现的该函数,效率是很慢的,特别是在高波特率下,如果要用的话,建议还是参考LL库,手写一个效率更高的)
一直用的也没啥问题,因为波特率很高,所以执行时间就不是太关心了,但是最近使用的SPI外设波特率低一些,这种方式就有点卡主循环的执行时间了,所以想用异步的方式,DMA的话我这边已经用满了,所以就使用中断的方式(HAL_SPI_TransmitReceive_IT)。
按照中断的玩法,编码完之后,调试发现,一直没进回调HAL_SPI_TxRxCpltCallback,加断点分析了一下原因,都是发送字节够了,但是接收字节不满足条件。
这个不符合 SPI全双工通信,因为作为主机,发完也意味着收完了,所以怀疑是HAL自身实现上有一点问题。
最后定位了一下问题
void HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi),该函数的实现上,对于主机模式下,发送接收的情况,不是太好。

这边又阅读了一下参考手册,SPI的中断就1个,接收/发送/错误,这3个是公用一个中断的,所以上面这个写法,假设中断源本身管理的没问题,收发1字节,也得进入两次IRQ才能处理完,对于我使用的场景,只有主机模式,全双工收发,那每次进入中断,应该都是发送和接收都要处理才对,所以这边调整了一下该函数。
也就是把发送放上面了,然后return注释掉,然后一切就正常了。也不会出现没有调用回调函数的情况了。
这边还需要注意一点:对于应用层,提交一次中断发送任务时,也就是调用HAL_SPI_TransmitReceive_IT,如果波特率特别高的情况下,有概率会出现,函数还没返回成功,但是数据就已经发送完毕,然后调用回调,才返回成功。这边对于应用层处理异步任务的时候需要注意。
32万+

被折叠的 条评论
为什么被折叠?



