近日一个项目,发现STM32单片机的串口在运行 一段时间后就不再能继续收到数据,但发送又正常的情况,我的串口采用的是阻塞式发送和DMA接收+空闲中断的处理方式。
经过查询资料和测试,发现第1种原因是正在发送数据的情况下又收到接收空闲中断,造成了空闲中断处理出错,未能正常启动DMA接收:
1)串口发送采用的函数HAL_UART_Transmit里有执行 __HAL_LOCK(huart)。
2)此时,如有接收空闲中断,则开始执行:
a)停止DMA接收: HAL_UART_DMAStop(huart)
b)获取接收数据
c)重启DMA操作:HAL_UART_Receive_DMA
该函数又执行一次 __HAL_LOCK(huart),根据该宏定义可知,产生阻塞,返回HAL_BUSY.因而未执行后续代码,如UART_Start_Receive_DMA等,所以串口的DMA接收和中断都未被打开。后续不再接收。
解决办法:
1)每次发送时检查上次发送的时间,做到间隔2ms以上,尽量避免串口发送时又正好收到对方的数据。
2)不再调用HAL_UART_Transmit函数。
自己编写如下串口发送函数:
static uint32_t last_send_time = 0;
HAL_StatusTypeDef USART_SendData(UART_HandleTypeDef *huart, uint8_t *pData, uint8_t Size, uint32_t Timeout)
{