使用串口收数据,接收端是这样写的,但是会丢帧,可能因为分包时候对bufstr的操作吗,怎么更好的写可以不丢包
int count = Serial.Port.BytesToRead;
byte[] buffer = new byte[count];
Serial.Port.Read(buffer, 0, count);
bufstr = bufstr + Encoding.ASCII.GetString(buffer);
Console.WriteLine(bufstr);
int i = bufstr.IndexOf("\r\n");
while (i != -1)//粘连分包
{
GetMessage(1, new string(bufstr.Take(i).ToArray()), null);//数据处理及显示
bufstr = new string(bufstr.Skip(i + 2).ToArray());
i = bufstr.IndexOf("\r\n");
}
维护一个全局变量list
接收到之后先add进list里,然后判断list里有没有换行符,有就从头到尾的执行,并把处理过的数据remove掉
你目前的代码,必须一次性接收到完整的数据,分两次来的时候会全部丢弃
你的代码中存在粘连分包的问题,这可能是导致丢帧的原因之一。在串口通信中,由于数据的传输速率和处理速度不一致,可能会出现粘连分包的情况,即多个数据包被粘合在一起,导致数据解析错误。因此,你需要在代码中处理这个问题,以避免丢帧。
在你的代码中,你使用了一个字符串变量 bufstr 来存储接收到的数据。每次读取到数据后,你都将其转换为字符串并追加到 bufstr 变量后面。然后,你使用一个循环来查找 bufstr 中的数据包,并调用 GetMessage 方法进行处理。
这里的问题在于,如果接收到的数据包仅包含部分数据,那么你可能会错过这个数据包,从而导致丢帧。比如,如果接收到的数据为 "hello\r\nworld\r\n",那么第一个数据包是 "hello\r\n",第二个数据包是 "world\r\n",但是如果你在读取数据时只读取了 "hello\r\n" 这个数据包的一部分,那么就会导致第二个数据包的解析错误。
因此,你需要修改代码来解决粘连分包的问题。一种常见的解决方法是使用一个缓冲区来存储接收到的数据,并在缓冲区中查找数据包。具体来说,你可以将接收到的数据追加到缓冲区中,然后查找缓冲区中的数据包,直到所有的数据包都被处理完毕。
下面是修改后的代码示例:
reasonml
Copy
byte[] buffer = new byte[Serial.Port.BytesToRead];
Serial.Port.Read(buffer, 0, buffer.Length);
bufferList.AddRange(buffer); // 将接收到的数据追加到缓冲区中
while (true)
{
int index = bufferList.IndexOf("\r\n"); // 查找缓冲区中的数据包
if (index == -1) break; // 如果没有找到数据包,跳出循环
string message = Encoding.ASCII.GetString(bufferList.ToArray(), 0, index);
bufferList.RemoveRange(0, index + 2); // 从缓冲区中移除已经处理过的数据包
GetMessage(1, message, null); // 处理数据包
}
在这个代码中,我们使用一个 List<byte> 类型的变量 bufferList 来存储接收到的数据。每次读取到数据后,我们将其追加到 bufferList 变量后面。然后,在一个循环中不断查找 bufferList 中的数据包,并调用 GetMessage 方法进行处理。在查找数据包时,我们使用 IndexOf 方法查找 "\r\n" 字符串,并返回其在缓冲区中的位置。如果找到了数据包,我们就调用 GetString 方法将数据包转换为字符串,并调用 RemoveRange 方法从缓冲区中移除已经处理过的数据包。注意,在调用 GetString 方法时,我们需要指定要转换的字节数和起始位置。
这样,你就可以避免粘连分包的问题,并可以更好地处理串口通信中的数据。
回答整理自chatgpt,如果有帮助麻烦采纳一下,谢谢啦!
private StringBuilder bufstr = new StringBuilder();
private void SerialDataReceivedEventHandler(object sender, SerialDataReceivedEventArgs e)
{
int count = Serial.Port.BytesToRead;
byte[] buffer = new byte[count];
Serial.Port.Read(buffer, 0, count);
string data = Encoding.ASCII.GetString(buffer);
bufstr.Append(data);
ProcessReceivedData();
}
private void ProcessReceivedData()
{
string data = bufstr.ToString();
int i = data.IndexOf("\r\n");
while (i != -1)
{
string message = data.Substring(0, i);
GetMessage(1, message, null);
data = data.Substring(i + 2);
i = data.IndexOf("\r\n");
}
bufstr.Clear();
bufstr.Append(data);
}