You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 04:23:12