[Interest] Parsing data from serialport
roland at logikalsolutions.com
Mon Apr 1 22:52:04 CEST 2019
You probably want to read as far as I got with this series.
Be sure to pull down the code for the various SerialKeypad implementations.
Here is a direct link to one of the zip files which was posted in case
you are impatient.
While that series wasn't meant to be a tutorial on serial communications
with Qt, quite a few nuggets of what you need to know are there.
I've got some other code floating around for doing serial communication
with Qt but, as you can tell, I don't check this list regularly.
You can do a search for CommLib because whenever I'm talking about
GreenLeaf CommLib from back in the days of DOS I'm generally talking
about how to do serial communications right. There are many many many
many gotchas today's platforms do not magically fix for you.
At the core of GreenLeaf's success/brilliance was the double ring
buffer. Their little TSR (under DOS) had one ring buffer for writing to
serial port and one the TSR stuff read characters into. It also kept
track of whether it wrapped either because you wrote too much or waited
too long to read. The ring buffer layer allowed the library to do
_exactly_ what every kid wants to do when they write their first serial
program. Read and write a packet. At the serial comm layer there is no
concept of a "packet" beyond what you configured to be a byte. While
many use 8-N-1, one cannot rely on that being the case.
Some devices won't even transmit a full 8 bits. Most newer ones will,
but don't count on it. In particular, scale systems which only need to
transmit the digits 0-9 and a "settled" indicator along with a checksum
or CRC of some kind were notorious for nibbles. Some could even use
their own form of packed decimal to keep the packet short for 300 baud
transmission. Adding insult to injury were those scales (and other
devices) which had no self control when it came to calculating the
CRC/CheckSum byte. They would have a start-packet indicator as well as
an end-packet value and the CRC/Checksum would end up being one of those
when the weight was just right.
Unlike TCP/IP, _you_ have to do all error handling and planning. Do not
assume a clear communications channel. Random electrical currents,
magnets or even someone slapping something down on a desk can generate
noise on the transmission line. (That last part applies more to modems
than hard wire port to port but it does apply to hard wire, specially if
the connection isn't screwed down tight. Just "feels tight" when pushed
on isn't good enough. An imperceptible amount of wiggle can introduce
noise on the line.)
If this is a production system, forget trying to do serial comm in your
primary (GUI) thread. In a perfect world with only happy path testing
you will get this to work and it will fail in the field. Something the
user does or the GUI does or the database or some other thing stolen
from an example program and left to run in the primary event loop will
take __just__ long enough for your intricate well designed
communications code to miss one or more critical control characters
causing it to get completely lost.
On 4/1/19 5:00 AM, interest-request at qt-project.org wrote:
> I'm trying to implement a serial connection with QIODevice (SerialPort). I
> would like to parse line by line (each line consists of multiple columns of
> data) and for this I found canReadLine().
> But as I understand I have to use startTransaction, because otherwise the
> buffer will not be used. I'm I correct?
> bool QIODevice::canReadLine() const
> Q_D(const QIODevice);
> return d->buffer.indexOf('\n', d->buffer.size(),
> d->isSequential() ? d->transactionPos :
> Q_INT64_C(0)) >= 0;
> So to read a full line, I have to open a QSerialPort and then start a
> Transaction. Then I have to wait a little bit (till data is in the buffer)
> and then I can use canReadLine. Am I correct? Is there a better way instead
> to wait a little bit? Or is it the wrong way to go?
Roland Hughes, President
More information about the Interest