如何处理串口不完整的接收数据?

时间:2013-07-05 09:02:08

标签: c# events buffer

我正在开发一个项目,我通过串口发送命令并等待响应处理。它遵循某种协议。

我面临的问题是我收到的回复是不完整的,所以我无法处理它。有些回复是在一个事件的早期发生的,其他一些事件将在之后发生。

我期待的回答如下:

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

但我只收到05-00,其余的都会收到,并且会不时变化,所以我无法预测。

我需要将响应存储到缓冲区,直到它完成然后处理它。我怎么能这样做?

我从串口接收的方式是这样的:

 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 ");
        }
    }

然后处理并显示在这里:

  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");
        }
    }

3 个答案:

答案 0 :(得分:1)

这应该做:

        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);

ResponseSize是您希望收到的消息长度。

答案 1 :(得分:0)

继续阅读,直到您有完整的回复。协议规范应指定如何判断响应是否完整。

答案 2 :(得分:0)

您可以使用列表或队列。但正如@David Schwartz所提到的,你必须找到合适的赞助人,也许是你想要阅读的链的大小,或者可能是发送者使用的协议。

这里是我用来读取的一个例子,7bit asccii。链使用格式{STX} {CHAIN} {ETX} {CRC}。但它有一个特殊情况,一个字节的答案{ACK}

从串口读取,直到得到一个完整的链,然后将该链作为字节数组返回:

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;
                    }
                }