如何等待下一个串口数据追加收集到的字节?
How to wait for next serial port data to be append with the collected byte?
我在读串口。但是其中一个响应大于 127,假设长度可以达到 4,294,967,295。正如我目前所面对的,数据长度是 250(这个值是动态的)。
目前到达的数据不完整。它出现在前 100 个,然后是下一个。响应的长度取决于缓冲区本身。
目前,这是我从串口读取响应的方式。
List<byte> serialByte = new List<byte>();
int bufferLen = 0;
void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (this.InvokeRequired)
{
this.Invoke(new SerialDataReceivedDelegate(SerialPort_DataReceived_Client), sender, e);
}
else
{
SerialPort_DataReceived_Client(sender, e);
}
}
void SerialPort_DataReceived_Client(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
if (!sp.IsOpen) return;
var buffer = (dynamic)null;
bool newData = true;
int BytesToRead = sp.BytesToRead;
AppendTextBox($"BytesToRead: {BytesToRead}");
byte[] temp = new byte[BytesToRead];
sp.Read(temp, 0, BytesToRead);
bufferLen = TLV.GetExpectedLength(temp);
AppendTextBox($"Buffer Len: {bufferLen}");
bool waitFullData = true;
bool isLenRetrieved = false;
serialByte.AddRange(temp);
buffer = new byte[bufferLen];
buffer = serialByte.ToArray();
DataReceived_TranslateData(buffer);
}
日志:-
示例内容长度在 127 以下
15:09:32.351167 PM - BytesToRead: 40
15:09:32.361139 PM - Expected Length: 40
样本内容长度在127以上
15:10:12.783806 PM - BytesToRead: 100
15:10:12.815695 PM - Buffer Len: 271
如果bufferLen
等于serialByte.Count
,数据就完成了,我会把byte[]
传递给方法DataReceived_TranslateData
。
我正在尝试执行以下操作,但是,我的 UI 冻结,我知道我的方法是完全错误的。
List<byte> serialByte = new List<byte>();
int bufferLen = 0;
bool waitFullData = true;
bool isLenRetrieved = false;
void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (this.InvokeRequired)
{
this.Invoke(new SerialDataReceivedDelegate(SerialPort_DataReceived_Client), sender, e);
}
else
{
SerialPort_DataReceived_Client(sender, e);
}
}
void SerialPort_DataReceived_Client(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
if (!sp.IsOpen) return;
var buffer = (dynamic)null;
bool newData = true;
int BytesToRead = sp.BytesToRead;
AppendTextBox($"BytesToRead: {BytesToRead}");
byte[] temp = new byte[BytesToRead];
sp.Read(temp, 0, BytesToRead);
bufferLen = TLV.GetExpectedLength(temp);
AppendTextBox($"Buffer Len: {bufferLen}");
while (waitFullData)
{
if (!isLenRetrieved)
{
bufferLen = TLV.GetExpectedLength(temp);
isLenRetrieved = true;
AppendTextBox($"Buffer Len: {bufferLen}");
}
if (newData)
{
serialByte.AddRange(temp);
newData = false;
}
if (bufferLen == serialByte.Count)
{
waitFullData = false;
break;
}
else
{
Thread.Sleep(100);
}
}
buffer = new byte[bufferLen];
buffer = serialByte.ToArray();
DataReceived_TranslateData(buffer);
}
如何等待下一个串口数据,直到长度与预期长度匹配?
首先,不要使用 this.Invoke
调用整个方法,只需将 UI 更新代码放入其中,就像您的 AppendTextBox
方法一样。
其次,不要在 DataReceived 事件中等待。因为每次串口获取数据都会触发这个事件。 while 循环只是阻止它。
你的代码应该是这样的:
List<byte> serialByte = new List<byte>();
int bufferLen = 0;
private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
if (!sp.IsOpen) return;
//other codes
int BytesToRead = sp.BytesToRead;
byte[] temp = new byte[BytesToRead];
sp.Read(temp, 0, BytesToRead);
serialByte.AddRange(temp);
//other codes
if (serialByte.Count >= bufferLen)
{
DataReceived_TranslateData(serialByte.GetRange(0, bufferLen).ToArray());
//clear the list if you need
}
}
我在读串口。但是其中一个响应大于 127,假设长度可以达到 4,294,967,295。正如我目前所面对的,数据长度是 250(这个值是动态的)。
目前到达的数据不完整。它出现在前 100 个,然后是下一个。响应的长度取决于缓冲区本身。
目前,这是我从串口读取响应的方式。
List<byte> serialByte = new List<byte>();
int bufferLen = 0;
void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (this.InvokeRequired)
{
this.Invoke(new SerialDataReceivedDelegate(SerialPort_DataReceived_Client), sender, e);
}
else
{
SerialPort_DataReceived_Client(sender, e);
}
}
void SerialPort_DataReceived_Client(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
if (!sp.IsOpen) return;
var buffer = (dynamic)null;
bool newData = true;
int BytesToRead = sp.BytesToRead;
AppendTextBox($"BytesToRead: {BytesToRead}");
byte[] temp = new byte[BytesToRead];
sp.Read(temp, 0, BytesToRead);
bufferLen = TLV.GetExpectedLength(temp);
AppendTextBox($"Buffer Len: {bufferLen}");
bool waitFullData = true;
bool isLenRetrieved = false;
serialByte.AddRange(temp);
buffer = new byte[bufferLen];
buffer = serialByte.ToArray();
DataReceived_TranslateData(buffer);
}
日志:-
示例内容长度在 127 以下
15:09:32.351167 PM - BytesToRead: 40
15:09:32.361139 PM - Expected Length: 40
样本内容长度在127以上
15:10:12.783806 PM - BytesToRead: 100
15:10:12.815695 PM - Buffer Len: 271
如果bufferLen
等于serialByte.Count
,数据就完成了,我会把byte[]
传递给方法DataReceived_TranslateData
。
我正在尝试执行以下操作,但是,我的 UI 冻结,我知道我的方法是完全错误的。
List<byte> serialByte = new List<byte>();
int bufferLen = 0;
bool waitFullData = true;
bool isLenRetrieved = false;
void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (this.InvokeRequired)
{
this.Invoke(new SerialDataReceivedDelegate(SerialPort_DataReceived_Client), sender, e);
}
else
{
SerialPort_DataReceived_Client(sender, e);
}
}
void SerialPort_DataReceived_Client(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
if (!sp.IsOpen) return;
var buffer = (dynamic)null;
bool newData = true;
int BytesToRead = sp.BytesToRead;
AppendTextBox($"BytesToRead: {BytesToRead}");
byte[] temp = new byte[BytesToRead];
sp.Read(temp, 0, BytesToRead);
bufferLen = TLV.GetExpectedLength(temp);
AppendTextBox($"Buffer Len: {bufferLen}");
while (waitFullData)
{
if (!isLenRetrieved)
{
bufferLen = TLV.GetExpectedLength(temp);
isLenRetrieved = true;
AppendTextBox($"Buffer Len: {bufferLen}");
}
if (newData)
{
serialByte.AddRange(temp);
newData = false;
}
if (bufferLen == serialByte.Count)
{
waitFullData = false;
break;
}
else
{
Thread.Sleep(100);
}
}
buffer = new byte[bufferLen];
buffer = serialByte.ToArray();
DataReceived_TranslateData(buffer);
}
如何等待下一个串口数据,直到长度与预期长度匹配?
首先,不要使用 this.Invoke
调用整个方法,只需将 UI 更新代码放入其中,就像您的 AppendTextBox
方法一样。
其次,不要在 DataReceived 事件中等待。因为每次串口获取数据都会触发这个事件。 while 循环只是阻止它。
你的代码应该是这样的:
List<byte> serialByte = new List<byte>();
int bufferLen = 0;
private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
if (!sp.IsOpen) return;
//other codes
int BytesToRead = sp.BytesToRead;
byte[] temp = new byte[BytesToRead];
sp.Read(temp, 0, BytesToRead);
serialByte.AddRange(temp);
//other codes
if (serialByte.Count >= bufferLen)
{
DataReceived_TranslateData(serialByte.GetRange(0, bufferLen).ToArray());
//clear the list if you need
}
}