如何处理串行端口不完整的接收数据
本文关键字:数据 串行端口 何处理 处理 | 更新日期: 2023-09-27 18:21:13
我正在处理一个项目,在该项目中,我通过串行端口发送命令,并等待响应处理。它遵循某种协议。
我面临的问题是我收到的回复不完整,所以我无法处理它。有些回复在一次活动中来得很早,有些则会在之后跟进。
我期待的回应是这样的:
05-00-0F-01-02-00-08-E2-00-60-03-11-73-D2-C1-86-5C
但我只会收到05-00
,其余的都会在之后,它会不时地变化,所以我无法预测。
我需要将响应存储到缓冲区中,直到它完成,然后进行处理。我该怎么做?
我从串行端口接收的方式是这样的:
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
try
{
int ByteToRead = serialPort1.BytesToRead;
//create array to store buffer data
byte[] inputData = new byte[ByteToRead];
//read the data and store
serialPort1.Read(inputData, 0, ByteToRead);
//invoke the display in another thread
this.BeginInvoke(new DelegateDisplay(Display), new object[] { inputData });
}
catch (SystemException ex)
{
MessageBox.Show(ex.Message, "Serial Port Error ");
}
}
然后在这里处理和显示:
public void Display(byte[] inputData)
{
try
{
TboxOutput.AppendText(BitConverter.ToString(inputData, 0) + "'n");
//Add recieved data to List
List<byte> Data = new List<byte>();
try
{
for (int i = 0; i < inputData.Length; i++)
{
Data.Add(inputData[i]);
}
}
catch (SystemException ex)
{
MessageBox.Show(ex.Message + "Data Process");
}
}
catch (SystemException ex)
{
MessageBox.Show(ex.Message, "Display Error");
}
}
这应该做:
const int timeout = 1000;
const int step = 100;
for (int t = 0; t < timeout; t += step)
{
Thread.Sleep(step);
if (serialPort1.BytesToRead >= ResponseSize)
break;
}
if (serialPort1.BytesToRead < ResponseSize)
{
serialPort1.DiscardInBuffer();
throw new Exception("Incorrect buffer size!");
}
serialPort1.Read(inputData, 0, ResponseSize);
其中,ResponseSize
是您期望收到的消息长度。
继续阅读,直到得到完整的回复。协议规范应该指定如何判断响应是否完整。
您可以使用列表或队列。但正如@David Schwartz所提到的,你必须找到合适的赞助人,也许是你试图阅读的链的大小,也许是发送者使用的协议。
这里有一个我用来读的例子,7bit asccii。链使用格式{STX}{CHAIN}{ETX}{CRC}。但它有一个特殊的情况,一个字节的答案{ACK}
它从串行端口读取,直到获得一个完整的链,并将该链作为字节数组返回:
public Byte[] RECIBE()
{
int count = serialPort1.BytesToRead;
if (count > 0)
{
List<Byte> bytes = new List<Byte>();
bool ETX = false;
while (ETX == false)
{
Byte b = Convert.ToByte(serialPort1.ReadByte());
if (b == 0x06)
{
bytes.Add(b);
return bytes.ToArray();
}
if (b != 0x03)
{
bytes.Add(b);
}
else
{
bytes.Add(b);
ETX = true;
}
}
Byte b2 = Convert.ToByte(serialPort1.ReadByte());
bytes.Add(b2);
return bytes.ToArray();
}
else
{
return null;
}
}