串口接收丢失数据问题

串口接收丢失数据问题

我在使用串口转usb接收解析数据,10分钟发一次,一小时应该收到六条数据,但是接收不稳定,有时候只能接到3条。
但是用串口助手去发送,就不会丢数据。

希望看到的老哥能指出哪里有问题。

//不考虑帧头帧尾和校验之类的问题
private List<byte> buffer = new List<byte>(2048);
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            Thread.Sleep(100);//添加延时
            // 读取有效的数据
            byte[] dataTemp = new byte[serialPort1.BytesToRead];
            serialPort1.Read(dataTemp, 0, dataTemp.Length);
            buffer.AddRange(dataTemp);
            int index = 1;            
            while (buffer.Count >= 1)
            {
                if (buffer[0] == 0x24) //判断收到的首字符 $
                {
                    if (buffer[index] != 0x24) //直到收到尾字符为$停下
                    {
                        index++;
                        if (index >= buffer.Count)
                        {
                            break;
                        }
                    }
                    else
                    {
                        byte[] ReceiveBytes = new byte[index];
                        buffer.CopyTo(0, ReceiveBytes, 0, index);
                        if (ReceiveBytes.Length >= 84)//实际发送的长度是111,但是需要只保留前84位的数据
                        {
                            AnalysisData(ReceiveBytes);//去解析数据
                            buffer.Clear();
                        }
                        else
                        {
                            buffer.Clear();
                            break;
                        }
                    }
                }
                else
                {
                    buffer.Clear();//接收字符不对,删除
                }
            }  
         }

serialPort1_DataReceived只能保证缓冲区里有数据
并不保证没有后续数据
你实际接收的字节数是111,如果波特率是9600,sleep(100)并不足以让111个字节发送完成
你应该给串口设置超时时间,然后开始while接收,直到接收满111个字节,或者超时,才能说明后续确实没有更新的数据了
或者在多次触发serialPort1_DataReceived执行的过程中,将收到的字节缓存在全局数组里,等待数据完整了再统一处理
另,调试的时候不要直接断点调,断点的时候等待时间足够长,那缓冲区里数据保证是全的
你应该在判断收到的数据无效的地方打个断点,看收到的到底是什么

串口通讯中丢失数据问题一般有以下几个原因:

发送方发送数据速度过快,导致接收方缓冲区已满,从而丢失部分数据。

接收方读取数据速度不够快,导致数据在接收缓冲区中被覆盖或丢失。

串口接收程序代码实现问题,导致不能完整读取数据,例如读取不完整,跳帧等问题。

在你的代码中,你在接收数据后添加了一个 100ms 的延时,这有助于解决接收数据速度不够快的问题。另外,你使用了一个 while 循环来判断是否已经接收到完整的一帧数据,这也是一种有效的方法。

但是,你的代码中似乎没有对数据接收缓冲区的大小进行限制,如果缓冲区溢出,则会导致丢失部分数据。建议在代码中增加一个接收缓冲区的最大容量限制,并在达到最大容量时清空缓冲区。

另外,在你的代码中使用了一个 buffer 列表来保存接收到的数据,建议在每次接收到完整的一帧数据后及时清空 buffer 列表,否则可能会导致接收到的数据被覆盖或丢失。

最后,由于你使用的是 C# 语言,建议考虑使用异步方式来进行串口通讯,以避免串口数据的阻塞问题。可以使用 SerialPort.DataReceived 事件来实现异步接收数据。


private List<byte> buffer = new List<byte>(2048);

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    Thread.Sleep(100); // Add a delay to prevent reading too quickly

    // Read incoming data
    byte[] dataTemp = new byte[serialPort1.BytesToRead];
    serialPort1.Read(dataTemp, 0, dataTemp.Length);
    buffer.AddRange(dataTemp);
    int index = 1;
    
    // Loop through the buffer to find complete messages
    while (buffer.Count >= 1)
    {
        if (buffer[0] == 0x24) // Check if first character is $
        {
            if (buffer[index] != 0x24) // Look for end character $
            {
                index++;
                if (index >= buffer.Count) // If end character not found, break out of loop
                {
                    break;
                }
            }
            else // End character found, message complete
            {
                byte[] ReceiveBytes = new byte[index];
                buffer.CopyTo(0, ReceiveBytes, 0, index);
                if (ReceiveBytes.Length >= 84) // Check if message length is correct
                {
                    AnalysisData(ReceiveBytes); // Process the message
                    buffer.Clear();
                }
                else // Message length incorrect, clear buffer
                {
                    buffer.Clear();
                    break;
                }
            }
        }
        else // Invalid message, clear buffer
        {
            buffer.Clear();
        }
    }
}

望采纳。

简单处理

Thread.Sleep(100);//添加延时
请把这里修改成 200,500 甚至可以是3*1000,对于你的应用而言 10分钟一次的数据,及时延后3秒大概率也嫩接受

至于原因楼上已经分析过了,如果对方200ms才发完,你收的就只有一半那么这条数据不符合于的尾部判定失败 丢弃一条
那么下一次在接收 你的buffer[0]头部判定又失败 又丢失一条

所以我们说按你的项目,简单的处理就是修改那个sleep时间,调整这个参数,以前叫调整“经验时间”,这个可以解决单台的问题,至于多台你就的写成配置文件,随时在现场配置了(毕竟每台硬件不一样,现场环境不一样,这种经验时间不一样)

如果你想真正完全解决这样的问题,请看这个帖子
https://bbs.csdn.net/topics/613171384