• C# 解决上位机串口接收数据丢失问题


    项目需要实现下位机和上位机的数据传输,看了网上的很多上位机的处理方法主要有两种。方法一是:port_DataReceived(SerialPort控件的数据接收方法,当有数据来临时会触发)会创建一个线程,因此当串口在等待数据时,不影响主窗体或主线程的操作。方法二是:使用缓存机制(参考:http://blog.csdn.net/jiqiang_paul/article/details/6914619)。首先通过定义一个成员变量List ReceBuf  new List(4096);用来存放所有的数据,在接收函数里,通过RecBuf.AddRange()方法不断地将接收到的数据加入到ReceBuf中,并同时对Recebuf中的数据进行检验,如果达到一定的长度并且校验结果正确(校验方法在发送方和接收方一致),再进行处理。

    经过测试发现这两种方法在数据包发送间隔小于200ms时,会出现数据丢包的问题,现在将这两种方法结合起来,同时将方法二改进为双缓存机制,经过测试发现可以解决数据的丢包的问题。
    一、在 public MainForm()中定义串口数据接收事件
      public MainForm()
            {
                InitializeComponent();
                serialPort_port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);//串口接收事件
                System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;//关闭夸线程检查
            }
    二、MainForm类下定义接收事件的委托并编写接收程序
     
      public delegate void PortDelegate();
            private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                PortDelegate proc_PORTGETDATA = new PortDelegate(getComData);
                IAsyncResult async_PORTGETDATA = proc_PORTGETDATA.BeginInvoke(null, null);
            }
    private List ReceBuffer = new List(4096);//串口接收一级缓存,默认分配一页内存并始终不超过 
     private byte[] DataTemp = new byte[10];//从一级缓存拷贝到二级缓存 
     private List DataBuf = new List(1000);//串口接收二级缓存,默认分配1000并始终不超过
     private byte[] DataTemp2 = new byte[10];//从二级缓存拷贝出来分析
     private byte[] DataAnalyBuf = new byte[8]; 
     public void getComData()
     { 
     try
     { 
     int n = serialPort_port.BytesToRead; 
     byte[] Receive = new byte[n]; 
     serialPort_port.Read(Receive, 0, Receive.Length); 
     bool DataCatched = false;//数据可以分析的标志
     //缓存数据 
     ReceBuffer.AddRange(Receive); 
     //完整性判断 
     while(ReceBuffer.Count >= 10)
     { 
     ////查看帧首和尾数据,判断准确性 
    //这里可以写成对数据的校验如CRC
    if (ReceBuffer[0] == 0x50 && ReceBuffer[9] == 0x42) 
     { 
     ReceBuffer.CopyTo(0, DataTemp, 0, 10); 
     DataBuf.AddRange(DataTemp); 
    DataCatched = true; 
     ReceBuffer.RemoveRange(0, 10);//获得一条正确的数据,删除缓存
     }
     else
     { 
     ReceBuffer.RemoveAt(0);//不是数据头,删除数据
     }
     }
     //分析数据 
     if (DataCatched == true) 
     { 
     while (DataBuf.Count > 0)
     {
     DataBuf.CopyTo(0,DataTemp2,0,10); 
    在这里写自己的数据分析
    DataBuf.RemoveRange(0, 10);
     } 
     }
     } catch { } 
     }
  • 相关阅读:
    BZOJ3149 CTSC2013 复原 搜索
    BZOJ5016 SNOI2017 一个简单的询问 莫队、前缀和、容斥
    THUWC2019-1:Reach out
    Luogu4630 APIO2018 Duathlon 圆方树、树形DP
    Luogu4606 SDOI2018 战略游戏 圆方树、虚树、链并
    BZOJ3720 Gty的妹子树 询问分块、主席树
    CF809E Surprise me! 莫比乌斯反演、虚树
    LOJ2542 PKUWC2018 随机游走 min-max容斥、树上高斯消元、高维前缀和、期望
    LOJ2541 PKUWC2018 猎人杀 期望、容斥、生成函数、分治FFT
    CF797F Mice and Holes 贪心、栈维护DP
  • 原文地址:https://www.cnblogs.com/cmblogs/p/11129313.html
Copyright © 2020-2023  润新知