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 { } 
 }
原文地址:https://www.cnblogs.com/cmblogs/p/11129313.html