C#Serialport没有在单个传输中接收所有字节

时间:2014-06-10 08:28:22

标签: c# serial-port

我正在使用以下代码通过串行端口接收十六进制数据,当它们是同一传输的一部分时,似乎这些传输中的一些被分解为2行。如何确保正确接收每个传输?

public void Receiver(object sender, SerialDataReceivedEventArgs e)
{
    string data;

    do
    {
        data = COMPort.ReadExisting();
    } while (COMPort.BytesToRead != 0);

    RxARR = data.ToCharArray().ToList();
    Dispatcher.Invoke(new MethodInvoker(Display)); // Start "Display" on the UI thread
} 

2 个答案:

答案 0 :(得分:6)

您永远不应该假设一次性提供来自串行端口的数据(顺便说一下,网络通信也是如此)。只有在收到所有内容后,您才需要确保代码接受消息。

一切很难定义。这可以是所有字符,直到定义的终止序列(例如\r\nEOL字节)或直到读取固定数量的字节。通常可以说,因为每个消息都可以被分段,如果没有定义的消息结束信号,则无法进行可靠的通信。

我们做的是:

  1. 创建StringBuilder
  2. 将所有内容读入StringBuilder
  3. 搜索终止序列
  4. StringBuilder删除所有内容,包括终止序列
  5. 处理该数据块
  6. 从3开始重复,直到找不到终止顺序
  7. 将剩余字符保留在StringBuilder中,因为这是新邮件的开头
  8. 伪代码:

    private StringBuilder serialBuffer = new StringBuilder();
    private string terminationSequence = "\r\n"; // Anything that can't be part of a message
    
    public void Receiver(object sender, SerialDataReceivedEventArgs e)
    {
        string data = COMPort.ReadExisting();
        serialBuffer.Append(data);
    
        string bufferString = serialBuffer.ToString();
    
        int index = -1;
        do
        {
            index = bufferString.IndexOf(terminationSequence);  
            if (index > -1)
            {
                string message = bufferString.Substring(0, index);
                bufferString = bufferString.Remove(0, index + terminationSequence.Length);
    
                HandleMessage(message);
            }
        }
        while (index > -1)
    
        serialBuffer = new StringBuilder(bufferString);
    } 
    

    顺便说一句:在DataReceived事件中循环是不可取的,因为只要有新内容可供阅读,SerialPort就会调用此事件。循环读取可能会干扰SerialPort默认执行的操作。所以:不要在那个事件中循环阅读! "循环"是SerialPort按顺序触发的事件。

答案 1 :(得分:0)

我的情况几乎相同。

像托尔斯滕所说的那样,数据有时并不会立刻出现。 也许是因为硬件或BaundRate ..

真正适合我的是:

        var end = '\r';
        int dataLength = _serialPort.BytesToRead;
        byte[] data = new byte[dataLength];
        int nbrDataRead = _serialPort.Read(data, 0, dataLength);

        RxString = Encoding.ASCII.GetString(data);
        txtCod.AppendText(RxString);

        if (RxString.IndexOf((char)end) > -1)
        {
            this.Invoke(new EventHandler(Final));   
        }