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

本文关键字:数据 串行端口 何处理 处理 | 更新日期: 2023-09-27 18:21:13

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

我面临的问题是我收到的回复不完整,所以我无法处理它。有些回复在一次活动中来得很早,有些则会在之后跟进。

我期待的回应是这样的:

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

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

这应该做:

        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是您期望收到的消息长度。

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

您可以使用列表或队列。但正如@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;
                    }
                }