How to wait for serial data received.

Huzo

Member
Joined
May 8, 2024
Messages
8
Programming Experience
Beginner
Hello guys. I am somewhat new to C# and .NET Framework. I am trying to make a program that sends data to device and receives it form a device using a serial port. First attempt was with a console app it worked fine for a concept. Now I am making a GUI app. So what I need is to send data to a device (I can do that) then wait for data to be received I am using SerialDataReceivedEvent, as dont know when will data come.
I have managed to display that data by using this.Invoke(new EventHandler()) and new method to do it here is that snippet.
C#:
private void  serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    byte[] dataInHex = new byte[6];
    string[] dataInHexSting = new string[6];

    
    serialPort1.Read(dataInHex, 0, dataInHex.Length);

    for(int i = 0; i < dataInHex.Length; i++)
    {
       dataInHexSting[i] = string.Format("{0:X2}", dataInHex[i]);
    }
    dataIn = string.Join(",", dataInHexSting);
    

    this.Invoke(new EventHandler(ShowData));

}

private void ShowData(object sender, EventArgs e)
{
    receive.Text = receive.Text + dataIn + " ";
}

I am not sure how does SerialDataReceived handler work. Is it like an interrupt routine in micro controllers and lets other part of the program run or is it just a method that pauses every thing.
I have been reading System.Io.Ports documentation and it seems that serial.Read() would be the best option because it waits for the data to be received if I am right.
 
It's like an interrupt handler, but the call happens on another thread rather than interrupting your UI thread.

Part of the transition into Windows GUI programming is also making the mental shift from imperative linear programming mental patterns to event driven programming mental patterns. Avoid polling if you can. Calling Read() without any data available to read is effectively like polling because you will stall out the UI thread.
 
Last edited:
So DataReceived Handler works on seperate thread. I am trying to receive data and compare it to pre defined data. Right now I am having a problem with that comparison and receiving. I am using Thread.Sleep function to slow down data transmit to a microcontroller. The problem is that If I make the Thread.Sleep() shorter than lets say 150 ms the program cant send the data properly to mico controller. If I bump up the baud rate in the app and on the microcontroller it would be too fast for the SPI channel on the microcontroller. And again if I make thread sleep more than 150 ms the dataIn variable starts to shift actual bytes (from expected 0x01,0xFF,0xFF,0x02,0xFF,0xFF to 0xFF,0xFF,0x02,0xFF,0xFF,0x01 and every received data is than shifted again). Right now I dont know how to move on.
 
And to add on to the answer. When using stand alone program for serial communication (tera term, hercules and other) My data is received as it should be received.
 
I suspect you have some other code that is is play and affecting things. Changing your delay between read operations shouldn't affect what you actually read out of the input buffer.

Please show us your code for reception as well as for sending.
 
Code written in my first reply is the receive code with event handler. I am using both in my app and on microcontroller so called "interrupts". Every time where something is received "Stop" the code ( as you said @Skydiver). I have 2 methods that have transmition in them. Here they are:
First method that send data via button click:
private void btn4_Click(object sender, EventArgs e)
{
    if (serialPort1.IsOpen)
    {
        data = textBox1.Text;
        byte[] dataOut = data.Split(',').Select(s=> Convert.ToByte(s,16)).ToArray();
        serialPort1.Write(dataOut,0,dataOut.Length);
        textBox1.Clear();
    }
}

Second method that is automated.:
private void btn3_Click(object sender, EventArgs e)
{

    if(serialPort1.IsOpen)
    {
      
      
        while(i<4)
        {

            serialPort1.Write(start, 0, 3);
            Thread.Sleep(200);
            serialPort1.Write(treset, 0, 3);
            Thread.Sleep(200);
            serialPort1.Write(tcom[i], 0, 3);
            Thread.Sleep(200);
          
            for(j=0; j<1000; j++)
            {
              
                //Thread.Sleep(10);
                if (dataIn.Equals(tans[i]))
                {
                    cont++;
                }
            }
            this.Invoke(new EventHandler(ShowData));

            if (cont>190) 
            {
                assur++;
                cont = 0;
            }else
            {
                assur--;
                cont = 0;
            }

            i++;
            serialPort1.Write(treset, 0, 3);
            Thread.Sleep(200);
            serialPort1.Write(stop, 0, 3);
            Thread.Sleep(200);
        }
      
    }
    if (assur > 0)
    {
        MessageBox.Show("Test passed", "Success!", MessageBoxButtons.OK, MessageBoxIcon.Information);
        assur = 0;
        i= 0;
    }
    else if (assur < 0)
    {
        MessageBox.Show("Test failed", "Fail", MessageBoxButtons.OK, MessageBoxIcon.Hand);
        assur = 0;
        i = 0;
    }
}

In second method as you can see I am using Thread.Sleep() methods. I have a suspicion that Thread.Sleep and for loop that compares dataIn with tans makes the code slow or too fast. As I have mentioned in last reply micro controller side code is fine. It receives correct data at expected time. And I know that this thread went from "How to wait for serial data received" to something deeper :rolleyes::rolleyes:
 
Last edited:
Back
Top Bottom