简体   繁体   中英

How to handle serial port incomplete received data?

I am working on a project where i send a command through serial port and wait for the response to process. it follows some kind of protocol.

the problem i am facing is the response i am receiving is incomplete, so i am unable to process it. Some the response comes early at one event and some others will follow afterwards.

the response i am expecting looks like this:

05-00-0F-01-02-00-08-E2-00-60-03-11-73-D2-C1-86-5C

but i will receive only 05-00 and the rest comes after and it changes from time to time, so i can't predict.

i need to store the response to a buffer until it is complete then process it. how can i do that?

the way i am receiving from serial port is like this:

 private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        try
        {
            int ByteToRead = serialPort1.BytesToRead;

            //create array to store buffer data
            byte[] inputData = new byte[ByteToRead];

            //read the data and store
            serialPort1.Read(inputData, 0, ByteToRead);

            //invoke the display in another thread
            this.BeginInvoke(new DelegateDisplay(Display), new object[] { inputData });
        }
        catch (SystemException ex)
        {
            MessageBox.Show(ex.Message, "Serial Port Error ");
        }
    }

then process and display at here:

  public void Display(byte[] inputData)
    {
        try
        {
            TboxOutput.AppendText(BitConverter.ToString(inputData, 0) + "\n");

            //Add  recieved data to List
            List<byte> Data = new List<byte>();

            try
            {
                for (int i = 0; i < inputData.Length; i++)
                {
                    Data.Add(inputData[i]);
                }
            }
            catch (SystemException ex)
            {
                MessageBox.Show(ex.Message + "Data Process");
            }


        }
        catch (SystemException ex)
        {
            MessageBox.Show(ex.Message, "Display Error");
        }
    }

This should do:

        const int timeout = 1000;
        const int step = 100;

        for (int t = 0; t < timeout; t += step)
        {
            Thread.Sleep(step);
            if (serialPort1.BytesToRead >= ResponseSize)
                break;
        }


        if (serialPort1.BytesToRead < ResponseSize)
        {
            serialPort1.DiscardInBuffer();
            throw new Exception("Incorrect buffer size!");
        }

        serialPort1.Read(inputData, 0, ResponseSize);

Where ResponseSize is the length of message you expect to recieve.

Keep reading until you have the complete response. The protocol specification should specify how you tell if the response is complete.

you could use lists, or queues. but as @David Schwartz mentioned, you have to figure the right patron, maybe the size of the chain you're trying to read, or maybe the protocol being used for the sender.

here an example I use to read, 7bit asccii. the chains usin format {STX}{CHAIN}{ETX}{CRC}. But it have a particular case, with an one byte answer {ACK}

this reads from serial port, till get a complete chain, and returns that chain as a byte array:

public Byte[] RECIBE()
                {
                    int count = serialPort1.BytesToRead;
                    if (count > 0)
                    {
                        List<Byte> bytes = new List<Byte>();
                        bool ETX = false;
                        while (ETX == false)
                        {
                            Byte b = Convert.ToByte(serialPort1.ReadByte());
                            if (b == 0x06)
                            {
                                bytes.Add(b);
                                return bytes.ToArray();
                            }
                            if (b != 0x03)
                            {
                                bytes.Add(b);
                            }
                            else
                            {
                                bytes.Add(b);
                                ETX = true;
                            }
                        }
                        Byte b2 = Convert.ToByte(serialPort1.ReadByte());
                        bytes.Add(b2);
                        return bytes.ToArray();
                    }
                    else
                    {
                        return null;
                    }
                }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM