C# Serialport 没有在单次传输中接收所有字节 [英] C# Serialport not receiving all the bytes in a single transmission

查看:116
本文介绍了C# Serialport 没有在单次传输中接收所有字节的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using the following code to receive hex data over the serial port, it seems that some of these transmissions are broken up into 2 lines when they are parts of the same transmission. How do I make sure that each transmission is received properly?

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
} 

推荐答案

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

You should never assume that data from a serial port is provided to you in one go (the same is true for network communication by the way). You need to make sure that your code accepts a message only if you have received everything.

一切都很难定义.这可以是所有字符,直到定义的终止序列(例如 \r\nEOL 字节)或直到读取固定数量的字节.一般可以说,由于每条消息都可能被分割,如果没有定义的消息结束信号,可靠的通信是不可能的.

Everything is hard to define. This can either be all characters until a defined termination sequence (for example \r\n or EOL byte) or until a fixed number of bytes is read. Generally one can say, as every message can be fragmented, reliable communcation is not possible without a defined end of message signal.

我们所做的是:

  1. 创建一个StringBuilder
  2. 将所有内容读入 StringBuilder
  3. 搜索终止序列
  4. 删除从 StringBuilder 到并包括终止序列的所有内容
  5. 处理那块数据
  6. 从 3 开始重复直到找不到终止序列
  7. 保留StringBuilder中剩余的字符,因为这是新消息的开始
  1. Create a StringBuilder
  2. Read everything into that StringBuilder
  3. Search for termination sequence
  4. Remove everything from the StringBuilder up to and including the termination sequence
  5. Process that chunk of data
  6. Repeat from 3 until termination sequence is not found
  7. Keep the remaining characters in StringBuilder, as this is the start of a new message

伪代码:

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 依次触发的事件.


By the way: Looping within your DataReceived event is not desired, as this event is called by the SerialPort whenever something new is ready to be read. Reading in a loop may interfere with what SerialPort is doing by default. So: Don't read in a loop within that event! The "loop" is the event being fired in sequence by SerialPort.

这篇关于C# Serialport 没有在单次传输中接收所有字节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆