Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
682 views
in Technique[技术] by (71.8m points)

c# - Why SerialDataReceivedEventArgs receive incomplete data?

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 + 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.

enter image description here

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

var end = '
';
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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 ( ) or line feeds ( ) 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 ).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...