为什么 SerialDataReceivedEventArgs 收到不完整的数据? [英] Why SerialDataReceivedEventArgs receive incomplete data?

查看:137
本文介绍了为什么 SerialDataReceivedEventArgs 收到不完整的数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在研究 IO 板.串行对象已初始化并侦听传入数据.我正在使用 SerialPort1.ReadExisting(); 读取传入数据,因为传入字符串预计将作为 {X000000}5E + \r\n 到达> 在每次阅读中.

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e){尝试{TextBox2.Invoke(new EventHandler(delegate{TextBox2.AppendText(SerialPort1.ReadExisting());}));}抓住{MessageBox.Show("无法打开端口", "错误");}}

当像这样使用 ReadExisting() 时,我得到了我想要的结果,我会得到{X"和}"之间的值,但是当我做一个拆分字符时,我总是得到关于索引的错误越界.我通过在读取时添加 Environment.NewLine 来改变读取方式以获取数据是否完整接收.结果将如下图所示.

我也根据 SO 答案尝试如下所示,但传入的字符串数据将与上图相同:-

var end = '\r';int dataLength = _serialPort.BytesToRead;字节[]数据=新字节[数据长度];int nbrDataRead = _serialPort.Read(data, 0, dataLength);字符串 RxString = System.Text.Encoding.ASCII.GetString(data);LogEvents($"串口数据:{RxString}");

<块引用>

这就像 {X000000}5E 的完整集合在拆分为 SerialDataReceivedEventArgs 时出现了 1-3 次.

我读错了吗?我还将波特率从 9600 增加到 19200,但传入的数据仍然与提供的图像相同.和IO板程序有关系吗?我对此不太确定.

解决方案

正如@jdweng 所指出的,串行端口 DataReceived 事件有点随机触发.它可能会触发中弦,而您只能收到一半的消息.您必须构建自己的字符串.大多数串行到串行通信使用回车符 (\r) 或换行符 (\n) 来确定消息已完成.从您告诉我们的情况来看,您似乎在末尾添加了 <CR><LF>,因此我们可以查找 LF 以知道我们获得了整个字符串.

char LF = (char)10;StringBuilder sb = new StringBuilder();string currentLine = string.Empty;private void serialPort1_DataReceived(对象发送者,System.IO.Ports.SerialDataReceivedEventArgs e){字符串数据 = serialPort1.ReadExisting();foreach(数据中的字符 c){如果(c == LF){sb.Append(c);CurrentLine = sb.ToString();sb.清除();//在此处解析 CurrentLine 或将其打印到文本框}别的{sb.Append(c);}}}

所以在上面的例子中,我正在寻找一个换行符来知道我得到了整个消息.(LF 或 \n).

I'm currently working on IO board. The serial object has been initialized and listen for incoming data. I'm reading incoming data using SerialPort1.ReadExisting(); as the incoming string expected to arrive as {X000000}5E + \r\n in every reading.

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    try
    {
        TextBox2.Invoke(new EventHandler(delegate
        {
            TextBox2.AppendText(SerialPort1.ReadExisting());
        }));
    }
    catch
    {
        MessageBox.Show("Couldn't open Port", "Error");
    }
}

When using ReadExisting() just like that, I got the result like I wanted and I will get the value of between "{X" and "}", but when I do a split char, I always got error regarding index out of bound. I change the way of reading by adding Environment.NewLine when reading to get whether the data is receive in a complete or not. The result will be like below image as expected.

I also try like below based from SO answer but incoming string data will be same as image above:-

var end = '\r';
int dataLength = _serialPort.BytesToRead;
byte[] data = new byte[dataLength];
int nbrDataRead = _serialPort.Read(data, 0, dataLength);

string RxString = System.Text.Encoding.ASCII.GetString(data);
LogEvents($"Serial port data: {RxString}");

It's like the full set of {X000000}5E is coming in 1-3 times in split to SerialDataReceivedEventArgs.

Am I reading the wrong way? I have also increase the baudrate from 9600 to 19200 but the incoming data still same as provided image. Do it has to do with the IO board program? I'm not so sure about this.

解决方案

As @jdweng pointed out, the serial port DataReceived event fires somewhat randomly. It could fire mid string and you could only receive half of the message. You'll have to build your own string. Most serial to serial communication use carriage returns (\r) or line feeds (\n) to determine that message is finished. From what you told us it looks like you tack on a <CR><LF> at the end, so we can look for the LF to know we got the whole string.

char LF = (char)10;
StringBuilder sb = new StringBuilder();
string currentLine = string.Empty;

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    string Data = serialPort1.ReadExisting();

    foreach (char c in Data)
    {
        if (c == LF)
        {
            sb.Append(c);

            CurrentLine = sb.ToString();
            sb.Clear();

            //parse CurrentLine here or print it to textbox
        }
        else
        {
            sb.Append(c);
        }
    }
}

So in the example above, I'm looking for a Line Feed character to know I got the whole message. (LF or \n).

这篇关于为什么 SerialDataReceivedEventArgs 收到不完整的数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆