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 { }
}