在我之前 的文章 嵌入式开发--STM32用DMA+IDLE中断方式串口接收不定长数据 中,介绍过用DMA+IDLE中断来接收不定长数据,就是利用DMA来接收数据,当一帧传送完成后,总线上出现一个完整的空闲帧的时间长度后,STM32会将IDLE标志置位,并产生一个中断。响应这个中断就可以接收不定长度的一帧了。
现在介绍一个更简单的方法,工作逻辑是一样的,但是更简明些。
HAL_UARTEx_ReceiveToIdle_DMA()函数,其原型如下:
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size),使用时需要使能串口中断,并开启IDLE中断
CubeMX中设置如下:

开启中断

设置DMA

然后就是软件
c
HAL_UARTEx_ReceiveToIdle_DMA(&huart3, uart3_rxbuf, UART3_RXBUF_LEN);
__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE); //开启IDLE中断
最后需要重写回调函数
c
// 接收事件回调函数,Size是本次接收到的数据长度
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
u16 i;
//调试接口uart3收到数据
if (huart->Instance == USART3)
{
// 1. 停止DMA传输
HAL_UART_DMAStop(huart);
// 2. 清除接收缓冲区
for(i=0; i<Size; i++)
{
uart3_rxdata[i] = uart3_rxbuf[i]; //从接收缓冲区提取数据
uart3_rxbuf[i] = 0; //这一行可以注释掉,留着它完全是为了调试时看得方便
}
// 3. 重新启动接收,DMA指针会自动归零,从头开始接收
HAL_UARTEx_ReceiveToIdle_DMA(huart, uart3_rxbuf, UART3_RXBUF_LEN);
uart3_rx_len = Size; //接收到的数据长度
}
}
此时,在uart3_rxbuf[]中保存的是数据,uart3_rx_len 是长度。
最后在主循环中的处理:
c
//调试接口uart3收到数据
if(uart3_rx_len != 0)
{
//
//做完所有处理之后,将长度清0
uart3_rx_len = 0;
}