最近在写一个读取ad7691数据的驱动时,SPI2设置为Receive only master模式,此时发现用SPI+DMA的HAL库函数HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)接收数据时(DMA为normal模式,以字节单位传输),通讯速率在300K以下时能够正常接收数据,而高于这个速率接收的数据就很乱,甚至收不到数据;如果不用DMA,用HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData)函数轮询接收数据时,通讯速率在600K以下时能够正常接收数据,而高于这个速率同样无法正常接收数据。拿示波器看了SPI的波形都是正常的,百思不得其解,后面去网上看到有人说要配置成全双工才能正常工作。
STM32 HAL库SPI+DMA接收数据的配置和使用方法_isyefeng-开放原子开发者工作坊
于是我将SPI设置成了Full-Duplex Master模式,调用 HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)和HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData)仍然不行,但是神奇之处在于,调用HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData, uint16_t Size)读写DMA函数,数据接收一下子就正常了,通讯速率轻轻松松跑到20M。此时好像只会进入发送完成中断而不会进入接收完成中断。
至于为什么会这样,具体原因我也不清楚,而且更让人疑惑的时,我的另一路SPI1设置为Transmit only master模式,DMA为normal模式,以字节单位传输,使用HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size)发送数据,通讯速率40M都没有问题;只能说以后使用SPI还是老老实实用全双工模式吧。