Click here to Skip to main content
15,885,216 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello,

I have an issue with reading data from the serial port and displaying it to a rich textbox.

The following is from my serial port received data event handler:

C#
void comPortDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            string msg = String.Empty;
            try
            {
                msg = comPort.ReadExisting();

             
            }
            catch (IOException ex)
            {
                //process any errors

               
            }
            //Display the data size of msg
            DisplayDataSize(Encoding.ASCII.GetByteCount(msg));

            //Display Data
            DisplayData(MessageType.Incoming, msg + '\n');


        }


Everything works fine except when I send certain commands to the device, I get the device's response in several triggers. For example, if I send a command to get the version of the device, it should display "VERSION 1.400240242....", but I am getting
"VERSION
1.40024..."

which is something odd. I tried creating a read function instead of using an event handler with the exact code and call the read function right after the write function in my main program. When I send the command to the device, I would get no response(eg. empty string). Then when I send command to the device again, I get the response back from both sends (eg. "VERSION 1.42.....\n VERSION 1.42...").

Also when running it in debug mode line by line, everything is displayed correctly.
I used backgroundWorker thread for the writing and receiving data portion of my code.

Does anyone know a possible fix for my problem?

Thank you

-dbzx
Posted

1 solution

In buttonStart_Click( ), we begin by setting the port name and baud rate. In our example PortName is COM1 but you can set it to any other port available on your computer. Notice the PortName is a string and must be in quotes. The baud rate must agree with the baud rate of whatever is on the other end of the serial connection. We then call the Open( ) function. If the port opened OK, we disable the Start button, enable the Stop button, and allow writing in textBox1.



C#
private void buttonStart_Click(object sender, EventArgs e)
  {
      serialPort1.PortName = "COM1";
      serialPort1.BaudRate = 9600;
  
      serialPort1.Open();
      if (serialPort1.IsOpen)
      {
          buttonStart.Enabled = false;
          buttonStop.Enabled = true;
          textBox1.ReadOnly = false;
      }
  }



Once the serialPort1 is open, any incoming serial characters will cause a DataReceived event to fire. Inside the event handler we read all existing characters from the internal serial receive buffer into string RxString. The next part is critical and not obvious. serialPort1 runs in it own separate thread behind the scenes. This thread cannot directly call any functions in the main thread of our application. However, a special function, Invoke( ), will allow it. So we use Invoke to call our DisplayText( ) function. RxString is the global string variable accessable by both threads.

C#
private void serialPort1_DataReceived
  (object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    RxString = serialPort1.ReadExisting();
    this.Invoke(new EventHandler(DisplayText));
}


Our DisplayText( ) function is simple. We just append the text in RxString to whatever is already in textBox1.


C#
private void DisplayText(object sender, EventArgs e)
  {
      textBox1.AppendText(RxString);
  }


The textbox1 KeyPress( ) function captures characters typed into textBox1 and writes them to serialPort1. Write( ) can only send characters from a char type array so we declare one with a length of [1] and assign the KeyChar value to it. With the arguments in Write( ), we tell it to send the characters in the buff, offset of 0 chars into the array, and a length of 1 char. We set the event to "Handled" to prevent the typed character from appearing in textBox1. If you want it to appear (local echo), omit the line.

C#
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    // If the port is closed, don't try to send a character.
    if(!serialPort1.IsOpen) return;

    // If the port is Open, declare a char[] array with one element.

    char[] buff = new char[1];

    // Load element 0 with the key character.
    buff[0] = e.KeyChar;

    // Send the one character buffer.
    serialPort1.Write(buff, 0, 1);

    // Set the KeyPress event as handled so the character won't
    // display locally. If you want it to display, omit the next line.

    e.Handled = true;
}


Clicking the Stop button calls buttonStop_Click( ). If serialPort1 is open, we close the port and set the button enables and textBox1 ReadOnly state back to their previous value.


C#
private void buttonStop_Click(object sender, EventArgs e)
 {
      if (serialPort1.IsOpen)
      {
          serialPort1.Close();
          buttonStart.Enabled = true;
          buttonStop.Enabled = false;
          textBox1.ReadOnly = true;
      }
 }



Last but not least, if the application is closed while serialPort1 is open, the port must be closed first or the program will hang.


C#
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
 {
     if (serialPort1.IsOpen) serialPort1.Close();
 }
 
Share this answer
 
Comments
dbzx734 26-Nov-12 16:49pm    
very informative but this has nothing to do with my question. everything works except the receive buffer having issue storing the data. some sort of timing issue because it works during debug

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900