zoukankan      html  css  js  c++  java
  • C# 解决串口接收数据不完整

    方法1:

    使 用缓存机制完成。首先通过定义一个成员变量List<byte> buffer = new List<byte> (4096);用来存放所有的数据,在接收函数里,通过buffer.AddRange()方法不断地将接收到的数据加入到buffer中,并同时对 buffer中的数据进行检验,如果达到一定的长度并且校验结果正确(校验方法在发送方和接收方一致),再进行处理。具体代码如下:代码 private List<byte> buffer = new List<byte>(4096);
    private void sp_DataReceived(objectsender, EventArgs e) //sp是串口控件
    {
    int n = sp.BytesToRead;
    byte[] buf = new byte[n];
    sp.Read(buf, 0, n);

    //1.缓存数据
    buffer.AddRange(buf);
    //2.完整性判断
    while (buffer.Count >= 4) //至少包含帧头(2字节)、长度(1字节)、校验位(1字节);根据设计不同而不同
    {
    //2.1 查找数据头
    if (buffer[0] == 0x01) //传输数据有帧头,用于判断
    {
    int len = buffer[2];
    if (buffer.Count < len + 4) //数据区尚未接收完整
    {
    break;
    }
    //得到完整的数据,复制到ReceiveBytes中进行校验
    buffer.CopyTo(0, ReceiveBytes, 0, len + 4);
    byte jiaoyan; //开始校验
    jiaoyan = this.JY(ReceiveBytes);
    if (jiaoyan != ReceiveBytes[len+3]) //校验失败,最后一个字节是校验位
    {
    buffer.RemoveRange(0, len + 4);
    MessageBox.Show("数据包不正确!");
    continue;
    }
    buffer.RemoveRange(0, len + 4);
    /////执行其他代码,对数据进行处理。
    }
    else //帧头不正确时,记得清除
    {
    buffer.RemoveAt(0);
    }
    }
    }

    方法2:

    接收数据的事件如下:
     void commPlc_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                byte[] buffer=new byte[commPlc.BytesToRead];
                commPlc.Read(buffer, 0, commPlc.BytesToRead);
                instr = "";
                foreach (byte b in buffer)
                {
                    instr += b.ToString("X2");
                }
    主程序中:
    outbuf = new byte[6] { 0x10, 0x02, 0x00, 0x5C, 0x5E, 0x16 };
                    commPlc.Write(outbuf, 0, outbuf.Length);
                    System.Threading.Thread.Sleep(600);

                    if (instr == "681212680002083203000000000002000100000501FF4716")
                    {
                      ………………………………
                     }

    解决办法有两种,
    一个是在DataReceived事件里加入
    System.Threading.Thread.Sleep(600); 
    byte[] buffer=new byte[commPlc.BytesToRead];
    这样可以等待缓冲区的数据缓冲好,一次接收数据,也就是只触发一次DataReceived事件

    方法二:
    将instr定义成全局变量,删除事件里的instr="";这样可以保证每次触发的时候不会清空instr

    以上内容仅仅是便于自己随手查阅使用

  • 相关阅读:
    python文件处理
    pycharm基础
    lvs集群DR模式,负载均衡
    JSP动作元素<jsp:include>和<jsp:param>的搭配使用
    Mybatis的动态SQL讲解
    hibernate多对多查询
    Hibernate配置文件与映射文件详解
    maven的不同版本下载及环境配置
    二级联动,例:根据省份选择市区
    关于JSP页面的静态包含和动态包含
  • 原文地址:https://www.cnblogs.com/wxmwanggood/p/7581633.html
Copyright © 2011-2022 走看看