通信数据报文的拆包解码

时间:2022-09-14 17:54:17

1.一般的数据报的格式

数据报的格式一般为:报头,长度,数据,校验和

2.解析的思路

读取数据,存在缓存中,检测缓存的头部数据,如果不是报头,删除,如果是报头,则从报头开始读取数据,计算校验和,校验和一致,存储数据,校验和不一致,将数据从缓存清空。

3.流程图


通信数据报文的拆包解码
通信数据报文的拆包解码

4.关键代码

private void Comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//如果正在关闭串口,忽略操作,直接返回
if (Closing)
return;
if (buffer.Count > 100)
{
buffer.Clear();
return;
}
try
{
Listening = true;
//从串口读入当前数据
int n = comm.BytesToRead;
byte[] buf = new byte[n];
comm.Read(buf, 0, n);
//先将读取到的数据加入缓冲区中
buffer.AddRange(buf);
//检查缓冲区(寻找报头并减去报头之前的数据)
TransCoding.CheckDataPacket(ref buffer);
//检查后的缓冲区内数据超过46字节,说明至少存在一个完整的包
if (buffer.Count >= 46)
{
byte[] data = new byte[46];
buffer.CopyTo(0,data, 0, 46);//从缓冲区中拿出一个完整的包
//报文解析
ReceiveDataPacket receivedPacket = new ReceiveDataPacket(data,TabelList);
//报文解析数据的显示
this.Invoke((EventHandler)(delegate
{
this.High_Label.Text=receivedPacket.Altitude.ToString();
}));
this.Invoke((EventHandler)(delegate
{
this.Temp_outLabel.Text = receivedPacket.Temperature_Out.ToString();
}));
this.Invoke((EventHandler)(delegate
{
this.HumiLabel.Text = receivedPacket.Humidity.ToString();
}));
this.Invoke((EventHandler)(delegate
{
this.GainLabel.Text = receivedPacket.Gain.ToString();
}));
this.Invoke((EventHandler)(delegate
{
this.TimeLabel.Text = receivedPacket.Width.ToString();
}));
this.Invoke((EventHandler)(delegate
{
this.DistanceLabel.Text = receivedPacket.Distance.ToString();
}));
this.Invoke((EventHandler)(delegate
{
this.DistanceLabel.Text = receivedPacket.Distance.ToString();
}));
this.Invoke((EventHandler)(delegate
{
this.VoltageLabel.Text = receivedPacket.Voltage.ToString();
}));

}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
Listening = false;//表明我用完了,UI可以关闭串口了
}

}

4.后期bug的讨论与修正