8

シリアルポート (Qt では QtSerialPort/QSerialPort を使用) から読み取っているデータは、改行 '\n' で区切られ、'\r' 文字を返します。これは、解析のためにそれを調べる方法です。行の長さは非常に長い場合がありますが、各行の形式からデータを抽出するのは非常に簡単です。

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

readData() は次のように定義されます。

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);
   }
}

ただし、このQIODevice::readLine()関数は非常に遅く、QIODevice::readAll() と比較して全周波数でデータを受信することを明確にブロックしています。

各行を解析するためreadLine()にループする必要がないように、誰かが関数を適切に使用する方法を説明できますか? 「ターミナル」Qt ウィジェットの例を使用して、この非同期シリアルポート読み取り機能を作成しました。readAll()QByteArray

事前に感謝します-これは、ここでまだ回答されていない一般的な問題のようです。

4

1 に答える 1

7

これは一般的なエラーです。は、データのチャンクごとに 1 回readDataだけ呼び出されます。必ずしも行ごとに 1 回呼び出されるとは限りません。

データが利用可能である限り、行を読み続ける必要があります。ウィジェット クラスでシリアル ライン読み取りを行うのも悪い設計です。別のオブジェクトに移動します。

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);
    ...
  }
}

エラーは、readData以下に示すように実装することでした。このようなコードは、読み取り可能な行数に関係なく、1 行しか読み取りません。呼び出しのたびに、読み取られずに残されたデータがますます蓄積されるため、「遅い」ように見えます。最終的にはヒープが不足します。

void readData() {
  // WRONG!
  if (m_port.canReadLine()) processLine(m_port.readLine());
}
于 2014-07-16T06:10:46.517 に答える