我正在使用以下代码通过串行端口接收十六进制数据,当它们是同一传输的一部分时,似乎这些传输中的一些被分解为2行。如何确保正确接收每个传输?
public void Receiver(object sender, SerialDataReceivedEventArgs e)
{
string data;
do
{
data = COMPort.ReadExisting();
} while (COMPort.BytesToRead != 0);
RxARR = data.ToCharArray().ToList();
Dispatcher.Invoke(new MethodInvoker(Display)); // Start "Display" on the UI thread
}
答案 0 :(得分:6)
您永远不应该假设一次性提供来自串行端口的数据(顺便说一下,网络通信也是如此)。只有在收到所有内容后,您才需要确保代码接受消息。
一切很难定义。这可以是所有字符,直到定义的终止序列(例如\r\n
或EOL
字节)或直到读取固定数量的字节。通常可以说,因为每个消息都可以被分段,如果没有定义的消息结束信号,则无法进行可靠的通信。
我们做的是:
StringBuilder
StringBuilder
StringBuilder
删除所有内容,包括终止序列StringBuilder
中,因为这是新邮件的开头伪代码:
private StringBuilder serialBuffer = new StringBuilder();
private string terminationSequence = "\r\n"; // Anything that can't be part of a message
public void Receiver(object sender, SerialDataReceivedEventArgs e)
{
string data = COMPort.ReadExisting();
serialBuffer.Append(data);
string bufferString = serialBuffer.ToString();
int index = -1;
do
{
index = bufferString.IndexOf(terminationSequence);
if (index > -1)
{
string message = bufferString.Substring(0, index);
bufferString = bufferString.Remove(0, index + terminationSequence.Length);
HandleMessage(message);
}
}
while (index > -1)
serialBuffer = new StringBuilder(bufferString);
}
顺便说一句:在DataReceived
事件中循环是不可取的,因为只要有新内容可供阅读,SerialPort
就会调用此事件。循环读取可能会干扰SerialPort
默认执行的操作。所以:不要在那个事件中循环阅读! "循环"是SerialPort
按顺序触发的事件。
答案 1 :(得分:0)
我的情况几乎相同。
像托尔斯滕所说的那样,数据有时并不会立刻出现。 也许是因为硬件或BaundRate ..
真正适合我的是:
var end = '\r';
int dataLength = _serialPort.BytesToRead;
byte[] data = new byte[dataLength];
int nbrDataRead = _serialPort.Read(data, 0, dataLength);
RxString = Encoding.ASCII.GetString(data);
txtCod.AppendText(RxString);
if (RxString.IndexOf((char)end) > -1)
{
this.Invoke(new EventHandler(Final));
}