首页 > 编程语言 >C#串口读写,遇到数据粘连怎么处理

C#串口读写,遇到数据粘连怎么处理

时间:2024-08-24 11:53:39浏览次数:10  
标签:packetStartIndex C# 读写 private buffer bufferLength 串口 byte 数据包

在读取串口数据时,可能会出现"粘连"的情况,即一次读取的数据中包含了多个数据包。这通常是由于数据的传输速度和读取速度不匹配导致的。

解决这种情况的常见方法有以下几种:

一、使用缓冲区

可以使用一个缓冲区来暂时存储读取的数据,并对缓冲区中的数据进行分析,找出完整的数据包。
示例代码:

private byte[] buffer = new byte[1024];
private int bufferLength = 0;

private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    int bytesRead = serialPort.Read(buffer, bufferLength, buffer.Length - bufferLength);
    bufferLength += bytesRead;

    // 在缓冲区中找出完整的数据包进行处理
    ProcessData();
}

private void ProcessData()
{
    // 在缓冲区中查找完整的数据包
    int startIndex = 0;
    while (true)
    {
        int endIndex = FindEndOfPacket(buffer, startIndex, bufferLength - startIndex);
        if (endIndex < 0)
            break;

        // 处理找到的完整数据包
        byte[] packet = new byte[endIndex - startIndex];
        Array.Copy(buffer, startIndex, packet, 0, packet.Length);
        ProcessPacket(packet);

        startIndex = endIndex + 1;
    }

    // 将未处理的数据移到缓冲区开头
    if (startIndex > 0)
    {
        Array.Copy(buffer, startIndex, buffer, 0, bufferLength - startIndex);
        bufferLength -= startIndex;
    }
}

二、使用超时机制

另一种方法是设置一个超时机制,在一定时间内没有收到新的数据时,认为一个数据包已经接收完毕。
示例代码:

private DateTime lastDataReceiveTime = DateTime.Now;
private const int TIMEOUT_MILLISECONDS = 100;

private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    lastDataReceiveTime = DateTime.Now;
    int bytesRead = serialPort.Read(buffer, bufferLength, buffer.Length - bufferLength);
    bufferLength += bytesRead;

    // 检查是否超时
    if ((DateTime.Now - lastDataReceiveTime).TotalMilliseconds > TIMEOUT_MILLISECONDS)
    {
        // 处理缓冲区中的数据
        ProcessData();
    }
}

三、使用特殊的分隔符

如果可以预知数据包之间有特殊的分隔符,可以使用这个分隔符来识别完整的数据包。
示例代码:

private byte[] buffer = new byte[1024];
private int bufferLength = 0;
private byte[] packetDelimiter = new byte[] { 0x0D, 0x0A }; // 回车换行

private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    int bytesRead = serialPort.Read(buffer, bufferLength, buffer.Length - bufferLength);
    bufferLength += bytesRead;

    // 在缓冲区中查找数据包分隔符
    int packetStartIndex = 0;
    int packetEndIndex = -1;
    while ((packetEndIndex = FindPacketDelimiter(buffer, packetStartIndex, bufferLength - packetStartIndex)) >= 0)
    {
        // 处理找到的完整数据包
        byte[] packet = new byte[packetEndIndex - packetStartIndex];
        Array.Copy(buffer, packetStartIndex, packet, 0, packet.Length);
        ProcessPacket(packet);

        packetStartIndex = packetEndIndex + packetDelimiter.Length;
    }

    // 将未处理的数据移到缓冲区开头
    if (packetStartIndex > 0)
    {
        Array.Copy(buffer, packetStartIndex, buffer, 0, bufferLength - packetStartIndex);
        bufferLength -= packetStartIndex;
    }
}

通过使用上述方法,可以有效地解决串口数据读取时出现的"粘连"问题,确保应用程序能够正确地处理接收到的完整数据包。

标签:packetStartIndex,C#,读写,private,buffer,bufferLength,串口,byte,数据包
From: https://blog.csdn.net/weixin_38812575/article/details/141497484

相关文章

  • C#串口读写,如果是按位读取,遇到有结束符号“0D0A”16进制终止符号的时候,怎么处理,并且保
    对于串口数据存在以0D0A(回车换行)作为结束符号的情况,可以按照以下步骤设计相应的处理逻辑:一、定义数据包结构首先定义一个数据包结构,包含数据包长度和实际数据内容两个部分。示例代码:publicstructSerialPacket{publicintLength;publicbyte[]Data;......
  • 怎么入门网络安全,学这两类证书就够了NISP或CISP_cisp和nisp2级题库一样吗
    其实网络安全这个门槛,对于当代的年轻人来说,不高也不低。其中NISP证书分为一级、二级、三级(专项),证书由中国信息安全测评中心颁发,持NISP二级证书可与免考兑换CISP证书。因为CISP报考需要工作经验,NISP填补了在校大学生无法考取CISP证书的空白,被称为“校园版CISP”。看到上一......
  • 目标检测实践过程中,遇到“No module named ‘torch._six’”报错的一个快速解决方案(无
    很多人在按照网络、书籍教程中的流程尝试自己实现一个基于Faster-RCNN的目标检测模型时,如果调用了PyTorch官方github上的文件时,coco_eval.py文件中会触发报错。1.报错原因PyTorch在2.0之后的版本中移除了_six,导致在coco_eval.py中调用torch._six失败2.解决方案(1)直接根......
  • ChatGPT等大模型高效调参大法——PEFT库的算法简介
    随着ChatGPT等大模型(LargeLanguageModel)的爆火,而且目前业界已经发现只有当模型的参数量达到100亿规模以上时,才能出现一些在小模型无法得到的涌现能力,比如in_contextlearing和chainofthougt。深度学习似乎朝着模型越来越大的方向一去不复。而对于这些通用的大模型如......
  • docker 修改容器内容后更新镜像的流程
    在Docker中,如果你修改了一个容器的内容并希望将这些更改保存为一个新的镜像,可以按照以下步骤进行:dockerversion:26.11.确保容器运行首先,确保你正在修改的容器是运行中的。如果容器已经停止,你需要启动它:dockerstart<container_id>2.进入容器并进行修改(如果尚未修改)你......
  • YSP_refs_cn_2016_适应症外及基础研究
    rhTNFR-Fc中文文献-2016-适应症外和基础研究 探索适应症外 随机对照试验[1][1] 杨雪阳,陈欢欢,郏文亭,等.重组人Ⅱ型肿瘤坏死因子受体-抗体融合蛋白治疗甲状腺相关性眼病的疗效.江苏医药,2016,42(9):1004-1006.浏览文摘 单臂观察[2][2] 李忱,刘晋河,郝......
  • 【C语言初级课程详解】第22课时-C语言结构体
    C 结构体C数组允许定义可存储相同类型数据项的变量,结构是C编程中另一种用户自定义的可用的数据类型,它允许您存储不同类型的数据项。结构体中的数据成员可以是基本数据类型(如int、float、char等),也可以是其他结构体类型、指针类型等。结构用于表示一条记录,假设您想要跟......
  • C语言——三子棋问题
     三子棋可以拆分为三部分:test.c——测试游戏的逻辑。game.h——放置游戏相关的头文件、符号声明、函数声明。game.c——游戏相关的函数实现。思路:保证游戏可以一直玩下去—— do...while循环打印一个简易菜单—— 函数menu();选择是否玩游戏——输入选择创建......
  • YSP_refs_cn_2016_RA
    rhTNFR-Fc中文文献-2016-RA 类风湿关节炎 随机对照试验[1-14][1] 李德明.重组人Ⅱ型肿瘤坏死因子受体-抗体融合蛋白联合甲氨蝶呤治疗类风湿关节炎疗效观察.世界最新医学信息文摘(连续型电子期刊),2016,16(62):145-146.浏览文摘[2] 庞丽霞.益赛普联合甲氨蝶呤治疗......
  • YSP_refs_cn_2016_其他关节炎及PsO
    rhTNFR-Fc中文文献-2016-其他炎性关节炎及PsO 银屑病 病例对照[1][1] 王维宁,方栩,黄琼.注射用重组人Ⅱ型肿瘤坏死因子受体-抗体融合蛋白联合阿维A治疗中重度斑块状银屑病的疗效和安全性观察.中华皮肤科杂志,2016,49(4):292-293.浏览文摘 幼年特发性关节炎......