Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
501 views
in Technique[技术] by (71.8m points)

c++ - QSerialPort readLine() extremely slow compared to readAll()

The data I'm reading from a serialport (in Qt, using QtSerialPort/QSerialPort) is separated by the newline ' ' and return ' ' characters, which is the way I intend to look at it for parsing. The line length may very, but it is very easy to extract the data from the format of each line.

//signal/slot connection on readyRead() is as follows:
connect(serial, SIGNAL(readyRead()), this, SLOT(readData()));

where readData() is defined as:

void MainWindow::readData()
{
   //As mentioned below, which I will reiterate, I have already tried the addition of 
   // canReadLine():
   if (serial->canReadLine()){
     QByteArray data = serial->readLine();
     //QByteArray allData = serial->readAll();
     parseSerialBytes(data);
     //console->putData(data);
     //console->putData(alldata);
   }
}

However, the QIODevice::readLine() function is extremely slow, and clearly blocking data from being received at full frequency compared to QIODevice::readAll()

Can someone please explain how to properly use the readLine() function so I don't have to loop through readAll() into the QByteArray to parse each line? I used the "terminal" Qt Widgets example to create this asynchronous serialport read functionality.

Thanks in advance - this seems to be a common problem I have not yet seen answered here.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This is a common error. The readData is called only once per a chunk of data, not necessarily once per line.

You need to keep reading lines as long as data is available. It is also a bad design to have serial line reading in a widget class. Move it to a separate object.

class Receiver : public QObject {
  Q_OBJECT
  QSerialPort m_port;
  QByteArray m_buffer;
  void processLine(const QByteArray & line) {
    ...
  }
  Q_SLOT void readData() {
    // IMPORTANT: That's a *while*, not an *if*!
    while (m_port.canReadLine()) processLine(m_port.readLine());
  }
public:
  Receiver(QObject * receiver = 0) : QObject(parent) {
    connect(&m_port, &QIODevice::readyRead, this, &Receiver::readData);
    ...
  }
}

Your error was to implement readData as shown below. Such code reads only one line no matter how many lines are available to be read. It'll appear "slow" since on each invocation there's more and more accumulated data that's left behind unread. Eventually it'll run out of heap.

void readData() {
  // WRONG!
  if (m_port.canReadLine()) processLine(m_port.readLine());
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...