Click here to Skip to main content
15,072,735 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have to create an aplication which reads the registers from a PLC at each 200ms. To do that I am using something like:

C#
SerialPort port=new SerialPort();
   bool dataRecieved=false;

   private void Form1_Load(object sender, EventArgs e)
   {
      port.RecievedBytesThrescold=21; //always the incoming message has to have 21 bytes

      timer1.Interval=200;
      timer1.Start();
   }

   private void ProcesTimier_Tick(object sender, EventArgs e)
   {
      if(dataRecieved)
      {
           dataRecieved=false;
           port.Read(buffer_rx,0,21);
           TranslateValues();
      }

      //Do something else based on the translated values

      if(port.IsOpen && connectected)
      {
         port.Write(buffer_tx,0,lengh);   //sends the command for a new reading
      }
   }

   private void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
   {
           Invoke(new EventHandler(DoUpdate));
   }
   void DoUpdate(object sender, EventArgs e)
   {
           dataRecieved = true;
   }


The problem is that from time to time, at random moments, my application freezies and when I go with the debug to see the execution line at which the application freezes, it points me to the port.Read(), but it doesn't retun any exeption. I have tried to use a try-catch block, but it didn't catch anything. I made time1.Interval=2000, but it didn't work either.
My question is if you know why my application freezies and points me to the port.Read(), but it doesn't catch any exception and how could I get over it?
Posted
Updated 6-Jun-12 22:31pm
v3
Comments
__John_ 7-Jun-12 5:10am
   
The port is probably waiting for 21 bytes to be received.
Myn92 7-Jun-12 5:15am
   
The port.RecievedBytesThrescold=21 means that the DataRecieved event should fire only when the port has recieved 21 bytes, so I do the reading only if I already have recieved 21 bytes
[no name] 8-Jun-12 1:15am
   
I think you'd better try another approach. Remove the Timer and dataRecieved boolean and in the port_DataReceived event rad the port and start another thread to process the data. In that case the port is read only when data is received.

1 solution

Your timer should not be necessary, and let port.RecievedBytesThrescold=1 (default). The only thing you can be sure of if you set it to 21, is that it will be at least 21 long. My suggestion is to do the buffering your self:
C#
byte[] buffer = new byte[50];
int endOfBuffer = 0;

void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
  int dataLength = _serialPort.BytesToRead;
  byte[] data = new byte[dataLength];
  int nbrDataRead = _serialPort.Read(data, 0, dataLength);
  if (nbrDataRead == 0)
    return;
      
  // Do some buffering
  Buffer.BlockCopy(data, 0, buffer, endOfBuffer, nbrDataRead);
  endOfBuffer += nbrDataRead;
  
  // Check if you got 21 bytes
  if(endOfBuffer >= 21)
  {
    byte[] plcDataArray = new byte[21];
    Buffer.BlockCopy(buffer, 0, plcDataArray, 0, 21);
    endOfBuffer -= 21;
    if(endOfBuffer != 0)
      Buffer.BlockCopy(buffer, 0, buffer, 21, endOfBuffer);
    
    // Signal your code that you got a complete data package from the plc
    if(SignalCompletePackageEvent != null)
      SignalCompletePackageEvent(this, EventArgsTakingYourByteArray(plcDataArray));   
  }
  
}

I have shared a very simple serial port app, and you're free to look at it Basic serial port listening application.
Good luck. NB: Always happy if you vote on the solution ;)
   
Comments
SoMad 8-Jun-12 15:52pm
   
My 5. Good answer and nice little serial port listener.

Soren Madsen

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