STM32L010F4 UART六字节数据包接收异常:最后一包丢失排查
UART接收六字节数据包的最后一包丢失问题
- 硬件平台:STM32L010F4
- 核心需求:通过UART接收包含SOF、EOF的6字节数据包,数据包存在两种发送场景:长时间空闲后发送、连续数据包间隔5ms发送;收到有效数据包后,对其中4个非SOF/EOF字节执行加减乘运算,重新打包后通过另一UART转发至主机
- 当前异常现象:
- 最初采用DMA接收时出现消息同步丢失问题,改用状态机方案后整体运行正常
- 连续发送多包(例如12包)时,最后一包无法转发:数据已存在RX缓冲区,但因未接收到EOF字节(仅收到EOF时才会递增缓冲区头索引),导致缓冲区头尾索引相等,无法触发数据包处理逻辑
- 在UART RX中断服务程序(ISR)的状态机中设置计数器标记缓冲区满,并在RX回调函数中设置满缓冲区标志;但调用
HAL_UART_Receive_IT启动下一字节接收后,中断未触发,断点无法命中 - 已通过RS-232 snooper确认数据源已发送EOF字节,且下次触发设备发送数据包时,旧数据包会被强制输出
相关代码实现
RX完成回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(RX_Pkt == 4) { DataFull = TRUE; // 缓冲区满标志 } HAL_UART_Receive_IT( &huart2, RX_Touch_Data, 1 ); }
USART2中断服务程序
void USART2_IRQHandler(void) { uint8_t Curr_Byte = *huart2.pRxBuffPtr; if(DataFull == TRUE) { DataFull = FALSE; // 此处断点未触发 } switch(Pkt_State) { case STATE_WAIT_SOF: { Data_Indx = 0; if( Curr_Byte == EETI_TD_PKT) { Msg_Buff[Buff_Head_Indx].RX_Data[Data_Indx] = Curr_Byte; ++Data_Indx; Pkt_State = STATE_RX_DATA; } } break; case STATE_RX_DATA: { Msg_Buff[Buff_Head_Indx].RX_Data[Data_Indx] = Curr_Byte; ++Data_Indx; if( Data_Indx == DATA_SIZE ) { Pkt_State = STATE_WAIT_EOF; } if (Msg_Buff[Buff_Head_Indx].RX_Data[0] == SPECIAL_PKT) { RX_Pkt++; // 用于检测缓冲区满的测试代码 } } break; }
内容的提问来源于stack exchange,提问作者nobby
相关产品推荐
相关产品推荐

