简体   繁体   中英

How to read all the bytes from Serialport as indicated by BytesToRead

I am trying to read data off a meter. The holy grail is 1000 samples per second which the device actually supports. Baud rate is 38400, Parity.None and Stopbits.One if that matters. I am using the binary mode to keep things as swift as possible. I plan using the DataReceived event as below.

private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        int bytesToRead = _serialPort.BytesToRead;
        byte[] data = new byte[bytesToRead];
        int actualBytesRead = 0;
        do
        {
            actualBytesRead = serialPort.Read(data, 0, bytesToRead);
        } while (actualBytesRead != bytesToRead);

        //At this point assume that the data byte array has all the data
    }

It seems that BytesToRead will return all the bytes which are available to read for that event. However as the link says

The SerialPort class buffers data, but the stream object contained in the
SerialPort.BaseStream property does not. Therefore, the SerialPort object
and the stream object might differ on the number of bytes that are 
available to read. When bytes are buffered to the SerialPort object, the 
BytesToRead property includes these bytes in its value; 
however, these bytes might not be accessible to the stream contained in
the BaseStream property. 

And Read returns only the number of bytes it has read. So as a precaution against this I plan to read continually till I get the number of bytes read same as what BytesToRead indicated for the event raised. However there are few points I am not clear on.

  • Will this even work. I am not sure if the data once read off the buffer of a serial port will remain to exist.
  • If not then while looping around should I keep the number of bytes to read equal to BytesToRead or should I adjust it for the number of bytes already read from the buffer.
  • I am pretty much hitting the buffer constantly till I get all the bytes. Is this right? Will this lead to locking issues in the sense that bytes will take longer to become available?
  • Is there any better way to get all the bytes as indicated by BytesToRead?

The following is wrong:

int actualBytesRead = 0;
do
{
    actualBytesRead = serialPort.Read(data, 0, bytesToRead);
} while (actualBytesRead != bytesToRead);

In each iteration of the loop you are always passing 0 for offset , so each time you read bytes you are overwriting bytes that were previously read.

I would rewrite it as follows:

for( int offset = 0;  offset < data.Length;  )
{
    int n = serialPort.Read( data, offset, data.Length - offset );
    offset += n;
}

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