Serial Port Read / Write Sync

I am trying to write a C # program in Visual Studio 2010 that communicates with a microcontroller through a serial connection. I can read and write normally to the port, I just don’t know how to make the send method wait until all the data from the previous send command is received before they are executed. I implemented a processed data handler so that it determines when the necessary amount of data was requested on the serial port. I just need to know how to get this to tell the send method that this port is free.

I planned to use a mutex, but I believe that the problem is not multithreaded. The same stream sends the lines to the serial port one by one, and the data received in response to the first request contradicts the second request.

In addition, if communication is performed by a single thread, will this thread wait for the processed data handler to not execute?

(both methods are in the same class)

My method of sending data:

//method for sending data
public void send(String s)
{

    sp.Write(s + "\r");
}

My processed data handler:

//data received event handler
private void dataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    string tmp;
    tmp = sp.ReadExisting();

    //put all received data into the read buffer
    readBuffer += tmp;

    //add various flag checks to determine end of transmission
    if (firmwareFlag)
    {
        if (readBuffer.EndsWith("\n"))
        {
            firmwareFlag = false;

            //trigger event to tell object owner data is ready
            dataReady(this, new CustomEventArgs(readBuffer, "firmware"));
            readBuffer = "";

        }
    }
    else if (parameterFlag)
    {
        if (System.Text.RegularExpressions.Regex.IsMatch(readBuffer, "K90", System.Text.RegularExpressions.RegexOptions.IgnoreCase))
        {
            parameterFlag = false;

            dataReady(this, new CustomEventArgs(readBuffer, "parameters"));
            readBuffer = "";

        }
    }
    else
    {
        dataReady(this, new CustomEventArgs(readBuffer, null));
        readBuffer = "";
    }

}
+5
source share
3 answers

I would use only the bool variable in the class and the timer. When the timer goes off, you check this bool and send data, if allowed.

boolean isAllowed;
DispatcherTimer tmr1;
//...etc
0
source

I have the same problem in the past, and I solved it like this:

SendAndWaitResponse, , , , - ( ) , :

//System.IO.Ports.SerialPort port; 
        //port.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived);
        void SendAndWaitResponse(String buffer, int expectedLenght, int timeoutInSeconds, Action<String> callback)
        {
            TimeSpan _timeout = new TimeSpan(0, 0, 0, timeoutInSeconds);

            //may not be necesary
            if (!string.IsNullOrEmpty(buffer) && buffer != "" && port != null)
            {
                //Remove current dataReceived event handler, as we will manually manage it for now, will restore later!
                this.port.DataReceived -= port_DataReceived;
                if (!this.port.IsOpen) this.port.Open(); // open the port if it was closed
                this.send(buffer); // send buffer, changed port.write(buffer) so it now usses your own send

                DateTime startToWait = DateTime.Now; //start timeout
                bool isTimeout = false;
                int totalRead = 0;
                String read = "";

                while (!(isTimeout) && totalRead < expectedLenght)
                {
                    do
                    {
                        if (port.BytesToRead > 0)
                        {
                            read += (char)this.port.ReadByte();
                            totalRead++;
                            //you can add a System.Threading.Thread.Sleep(int); if all bytes come in parts
                        }
                    } while (port.BytesToRead > 0);
                    isTimeout = (DateTime.Now.Subtract(_timeout) >= startToWait);
                }

                this.port.DataReceived += port_DataReceived; // restore listener
                callback(read); //invoke callback!!!
            }
        }
0

If you want to check if there are no bytes sent to the device (bytes in the write buffer), you can read the BytesToWrite property.

SerialPort.BytesToWrite Property

0
source

All Articles