1

I can't figure out what my SerialPort.DataReceived event handler is doing... It gets triggered when there are no data sent by my controller, and just in a very specific case.

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    // Invoke all code in another method to enable GUI updates from subthread
    if (this.InvokeRequired)
    {
        this.Invoke((MethodInvoker)(() => OnDataReceived(sender, e)));
    }
    else
    {
        OnDataReceived(sender, e);
    }
}

private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
{
    // COPY DATA FROM SERIAL BUFFER AND DISPLAY
    SerialPort spL = (SerialPort)sender;
    byte[] buf = new byte[spL.BytesToRead];
    Console.WriteLine("DATA RECEIVED!");
    spL.Read(buf, 0, buf.Length);
    foreach (Byte b in buf)
    {
        Console.Write(b.ToString() + " ");
    }
    Console.WriteLine();
    //Console.WriteLine(BitConverter.ToString(buf, 0, buf.Length)); // hexString
    switch (buf[0])
    {
        case GEN:
            if (next_op == rdGEN) // if General data requested, decode it
            {
                DecodeGEN(buf);
            }
            break;
        case BAS:
            if (next_op == rdSingle || next_op == rdAll) // if BAS or All data requested, decode BAS (and continue if All)
            {
                DecodeBAS(buf);
            }
            else if (next_op == wrSingle || next_op == wrAll) // if BAS or All data written, decode BAS response (and continue if All)
            {
                DecodeBASerr(buf);
            }
            break;
        case PAS:
            if (next_op == rdSingle || next_op == rdAll) // if PAS or All data requested, decode PAS (and continue if All)
            {
                DecodePAS(buf);
            }
            else if (next_op == wrSingle || next_op == wrAll);  // if PAS or All data written, decode PAS response (and continue if All)
            {
                DecodePASerr(buf);
            }
            break;
        case THR:
            if (next_op == rdSingle || next_op == rdAll) // if THR or All data requested, decode THR (and discard further data)
            {
                DecodeTHR(buf);
            }
            else if (next_op == wrSingle || next_op == wrAll) // if THR or All data written, decode THR response (and discard further data)
            {
                DecodeTHRerr(buf);
            }
            break;
    }
}

Basically I get a sequence of bytes sent from my controller and then I decode them to update GUI controls. This is an example:

82 24 41 18 0 15 26 35 50 60 70 80 90 100 0 80 85 90 100 100 100 100 100 100 54 1 43 
DATA RECEIVED!

The crazy weird thing is that in the only and very specific case where my byte array contains the number "26" as [6] element, the serialPort1_DataReceived gets called an extra time, and basically my program crash at switch buf [0] instruction since the buffer is empty https://i.stack.imgur.com/zf59Y.png. The strange thing is that DataReceived event shouldn't even be triggered with no data being passed! I tryed all accepted values for my program from 0 up to 100, and only "26" triggers this strange behaviour and it makes no sense at all to me...

  • 26 is ASCII EOF, for what it's worth. Type `copy con foo.txt` at the DOS command line, type a line of text, and press Ctrl+Z. – 15ee8f99-57ff-4f92-890c-b56153 Jan 15 '18 at 17:45
  • 1
    Character 26 (0x1A) was originally the "End Of File" character : see this https://stackoverflow.com/questions/12483711/serialdata-eof-circumstances – PaulF Jan 15 '18 at 17:45
  • 1
    Also see second paragraph of the [DataReceived Event](https://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived(v=vs.110).aspx) documentation Remarks section. You may have no bytes in the data buffer - hence the "program crash". Check for BytesToRead is zero & exit if it is. – PaulF Jan 15 '18 at 17:50
  • Data will not be received in one chunk. You code has to be able to combine data from multiple OnDataReceiveEnvents. So you have to either terminate the message with a character that is not part of the message or Add a Byte count to beginning of the message so you know where the message ends. The issue could be on the transmit function and not the receive method. – jdweng Jan 15 '18 at 18:15
  • "The DataReceived event is also raised if an Eof character is received, regardless of the number of bytes in the internal input buffer and the value of the ReceivedBytesThreshold property." Damn, I would have never thought about that.. Basically running the debug what happen is my DataReceived gets called once with filled buffer and it works just fine, and then it gets called a second time (because the string it read before contained the EOF char???) but this second time the buffer is empty and thus an exception is raised. So I guess I will just check if buf array is empty and make a return... – UnlimitedSlime Jan 15 '18 at 18:25
  • Still I can't understand: I would expect my program to read up to the EOF char and then exits, but in my case it reads all the buffer just fine, execute all the remaining portion of code contained in the DataReceived method and, after finishing all the work it had to do, it triggers the DataReceived event again, but this time with an empty input buffer. Why does it behave in this way? – UnlimitedSlime Jan 15 '18 at 18:33

0 Answers0