C#从串口读取所有缓冲区数据

Read all buffer data from serial port with C#

我在 C# 中使用 System.IO.Ports 从串行端口读取数据时遇到一些问题。唯一有效的方法是 "Read" 方法,但它只读取 "defined" 个字符,我需要像 "Tera Term" 或 "Hercules" 那样读取所有可用数据。这是我读取缓冲区的 DLL 方法:

public String ReadMessage(String port, int timeout, int dataSize)
{
    String res;

    try
    {
        _serial_port = new SerialPort();
        _serial_port.PortName = port;
        _serial_port.BaudRate = 19200;
        _serial_port.Parity = Parity.None;
        _serial_port.DataBits = 8;
        _serial_port.StopBits = StopBits.One;
        _serial_port.Handshake = Handshake.None;
        _serial_port.ReadTimeout = timeout;
        _serial_port.DtrEnable = true;
        _serial_port.RtsEnable = true;

        _serial_port.Open();
        _serial_port.DiscardInBuffer();

        int totalBytes = _serial_port.BytesToRead;

        if (totalBytes > 0)
        {
            byte[] buffer = new byte[totalBytes];
            _serial_port.Read(buffer, 0, totalBytes);
            res = ByteArrayToString(buffer);                   
        }
        else
        {
            byte[] buffer = new byte[dataSize];

            for (int len = 0; len < buffer.Length;)
            {
                len += _serial_port.Read(buffer, len, buffer.Length - len);
            }

            res = ByteArrayToString(buffer);                    
        }

        _serial_port.Close();

        return res;
    }
    catch (Exception ex)
    {
        if (ex is UnauthorizedAccessException || ex is TimeoutException)
        {
            _serial_port.Close();
        }

        return ex.ToString();
    }
}

我知道还有其他读取数据的方法,例如:"ReadByte"、"ReadChar"、"ReadExisting"、"ReadLine" 和 "ReadTo" 但 none 他们都在工作,我是不是做错了什么?

串口是流设备,可以连续接收数据。你需要设置一个定时器,只要串口打开,就可以不断地检查缓冲区中是否有任何东西,并尽快将其复制到缓冲区或磁盘上的文件中,以防止缓冲区溢出。

您需要检查数据内容以了解接收到的内容以及接收到所有数据的时间。这取决于发件人。你不能只说接收所有要接收的东西,就串行端口而言,它是一个连续的流。实际数据需要指定协议、启动和停止条件。

编辑

这是我用来通过 usb 到 rs232 设备以 5mbit/sec 的速度捕获软盘数据的代码片段:

    // Capture handler
    private void timer2_Tick(object sender, EventArgs e)
    {
        // Read data from serial port, poll every 10ms
        // If data is there, read a block and write it to array
        int bytestoread = 0;
        //byte buf;

        timer2.Stop();
        try
        {
            bytestoread = serialPort1.BytesToRead;
        }

        catch (InvalidOperationException ex)
        {
            tbr.Append("Serial connection lost. Exception type:" + ex.ToString());
            if ((uint)ex.HResult == 0x80131509)
            {
                timer2.Stop();
            }
        }

        if (serialPort1.IsOpen)
        {
            if (bytestoread != 0)
            {
                bytespersecond += bytestoread;

                byte[] temp = new byte[bytestoread];

                if (serialPort1.IsOpen)
                    serialPort1.Read(temp, 0, bytestoread);

                tempbuffer.Add(temp);
                processing.indexrxbuf += bytestoread;
                recentreadbuflength += bytestoread;

                //update the scatterplot, this may have a performance hit
                processing.rxbuf = tempbuffer.SelectMany(a => a).ToArray();
                rxbuf = processing.rxbuf;
                if (Setrxbufcontrol == null) return;
                Setrxbufcontrol();

            }
            timer2.Start();
        }
    }

串口设置代码。我定义了大缓冲区以防止溢出:

        serialPort1.BaudRate = 5000000;
        serialPort1.NewLine = "\r\n";
        serialPort1.ReceivedBytesThreshold = 500000;
        serialPort1.ReadBufferSize = 1048576;

编辑 2

从串口读取的步骤:

  1. 定义一个接收数据数组来保存数据
  2. 打开串口
  3. 设置计时器以连续读取数据,直到用户点击断开连接按钮
  4. timer tick 方法检查串行缓冲区中数据的长度,然后将该长度读入步骤 1 中定义的接收缓冲区。通过将串行缓冲区长度添加到静态变量来跟踪接收到的总数据。
  5. 在另一个计时器中,您可以检查接收到的数据数组中是否有新行。将所有数据复制到字符串数组或文本框。或者只是将数据作为字符串复制到文本框中以查看其中的内容。