Why serialport invokes readAll() twice or more?
-
I'm creating a program which sends and gets data to/from serial ports using QSerialPort.
Why when I'm using readyRead signal, I am reading not all data from port? My hardware on com just echoing incoming data.
here is my log:
@formed data "123456789"
sent data "123456789"
received data: "1234"
received data: "567"
received data: "89"@Is there any way to read all the information from port? Maybe I have to set delay or buffer before printing it?
If I set baud rate to 115200 bps - I'm almost always get whole string I sent. -
Oh...i forgot to mention that i already have a workaround for it. I create a class member QByteArray m_data. If i send a message i clear the bytearray and on receive i simply append the data. So it's clear.
The next step is to check if the message is completed by checking that the first token is STX-Start of transmission and check that the last received token is EOT-End of transmission and if possible, check the checksum.
The easiest way is to append on receive and clear the receice buffer after you send your request.
-
I guess it is related to the fact that CPU is much faster than a serial port.
QSerialPort reads data in a loop (see below) and if result is 0 then loop is finished. It is possible that some bits come a microsecond late and call to read() will return 0. Next call to readAll() will pickup the next set of bits.
I think the approach that jensen82 uses is the only solution here if you have send/recv cycle.
- Qt5.2.1/5.2.1/Src/qtbase/src/corelib/io/qiodevice.cpp
@
if (d->isSequential() || (theSize = size()) == 0) {
// Size is unknown, read incrementally.
qint64 readResult;
do {
result.resize(result.size() + QIODEVICE_BUFFERSIZE);
readResult = read(result.data() + readBytes, result.size() - readBytes);
if (readResult > 0 || readBytes == 0)
readBytes += readResult;
} while (readResult > 0);
} else {
@
- Qt5.2.1/5.2.1/Src/qtbase/src/corelib/io/qiodevice.cpp
-
This is normal behavior!
QtSerialPort works in a non-blocking asynchronous mode (on event-based mode) when operation of reading comes back immediately.
In this case, in case of origin of an EV_RXCHAR event, the internal logic of class reads all data from the FIFO (which available in FIFO in current moment) in the internal buffer of a class, and emit readyRead().
So, the method readAll() (or any read()) just return the content of the internal read buffer; the method bytesAvailable() - returns a size of the internal read buffer. And do nothing anymore.
To learn that a whole packet is received can be do:
-
Call the bytesAvailable() in each readyRead() and do nothing more. In case bytesAvailable() == expectedLength we can be sure that package is received and then we can do read and process package.
-
At first trigger of the readyRead() can be run the QTimer. The timeout() signal will be signalize to us that package is received or occured an timeout error (depends on your handling way).
-
Use the some communication protocol, where can be specified the size of the package, and, maybe, other control fields.. In this case also can be combine way 1 and 2 and something else.
Anyway, the behavior of QtSerialPort is a streaming mode, where there is no concept of the beginning and the end of packet. You shall define it independently, having selected your specific solution of handling.
-