简体   繁体   English

使用C#从串行端口读取所有缓冲区数据

[英]Read all buffer data from serial port with C#

I have some problems using System.IO.Ports in C# to read data from a serial port. 我在C#中使用System.IO.Ports从串行端口读取数据时遇到一些问题。 The only method thar works is the "Read" method, but it only read "defined" number of characters and i need to read all available data like "Tera Term" or "Hercules" do. 唯一有效的方法是“读取”方法,但它只能读取“已定义”的字符数,我需要读取所有可用的数据,例如“ Tera Term”或“ Hercules”。 Here is my DLL method that reads the buffer: 这是我的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();
    }
}

I know there are other methods to read data like: "ReadByte", "ReadChar", "ReadExisting", "ReadLine" and "ReadTo" but none of them are working, am i doing something wrong? 我知道还有其他读取数据的方法,例如:“ ReadByte”,“ ReadChar”,“ ReadExisting”,“ ReadLine”和“ ReadTo”,但是它们都不起作用,我在做错什么吗?

The serial port is a stream device, it can continuously receive data. 串行端口是一种流设备,它可以连续接收数据。 You'll need to set a timer as long the serial port is open to continuously check if there's anything in the buffer and copy it to a buffer or file on disk as soon as possible to prevent a buffer overflow. 只要串行端口处于打开状态,就需要设置一个计时器,以连续检查缓冲区中是否有任何东西,并尽快将其复制到缓冲区或磁盘上的文件中,以防止缓冲区溢出。

You need to check the data contents to find out what is received and when all of it is received. 您需要检查数据内容以找出接收到的内容以及何时接收到所有数据。 This depends on the sender. 这取决于发送者。 You can't just say receive all there is to receive, it's a continous stream as far as the serial port is concerned. 您不能只说接收所有要接收的内容,就串行端口而言,它是连续的。 The actual data needs to specify the protocol, start and stop conditions. 实际数据需要指定协议,开始和停止条件。

EDIT 编辑

Here's a code snippet I use to capture floppy disk data through a usb to rs232 device at 5mbit/sec: 这是我用来通过USB以5mbit / sec的速度将音频数据通过USB捕获到rs232设备的代码片段:

    // 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();
        }
    }

setup code for serial port. 串行端口的设置代码。 I defined large buffers to prevent overflows: 我定义了大缓冲区以防止溢出:

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

EDIT 2 编辑2

Steps to read from a serial port: 从串行端口读取的步骤:

  1. Define a received data array to hold the data 定义接收的数据数组以保存数据
  2. Open serial port 打开串口
  3. Set a timer to read data continuously until user hits disconnect button 设置计时器以连续读取数据,直到用户按下断开连接按钮为止
  4. timer tick method checks the length of data in serial buffer, then read that length into the receive buffer defined in step 1. Keep track of total received data by adding the serial buffer length to a static variable. 计时器滴答方法检查串行缓冲区中的数据长度,然后将该长度读取到步骤1中定义的接收缓冲区中。通过将串行缓冲区长度添加到静态变量中来跟踪接收的总数据。
  5. In another timer you could check the received data array for new lines. 在另一个计时器中,您可以检查接收到的数据数组是否有新行。 Copy all data to an array of strings, or to a textbox. 将所有数据复制到字符串数组或文本框。 Or just copy the data as a string to the textbox to see what's in it. 或者只是将数据作为字符串复制到文本框中以查看其中的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM