简体   繁体   中英

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. 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. Here is my DLL method that reads the buffer:

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?

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:

    // 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

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.
  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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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