1. ホーム
  2. c++

[解決済み] Qt5.13.1のQSerialPortを動作させる方法は?

2022-02-12 14:15:21

質問

問題点

QSerialPort Qt ライブラリのバージョン 5.13.1 からは、Windows 7 および 10 で物理的にデータが出力されません。

この問題を説明するために、次のような設定を用意しました。

  1. ハードウェア

物理的なシリアルポート(COM1)を持つPCと実際のシリアルデバイスとの接続をテストしましたが、デモのためにPCのDSubコネクタのピン2と3、すなわちTxとRxを接続して簡単なループバックを作りました。

  1. ソフトウェア

この問題は、私が作成したGUIアプリケーションでも、Qtに同梱されている公式サンプルでも発生します。しかし、デモのために、私は非常に基本的なコンソールアプリを書きました。

SerialBug.pro

QT -= gui
QT += serialport

CONFIG += console

SOURCES += \
        main.cpp

main.cpp

#include <QCoreApplication>
#include <QSerialPort>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QSerialPort port("COM1");

    port.setBaudRate(QSerialPort::Baud4800);
    port.setDataBits(QSerialPort::Data8);
    port.setStopBits(QSerialPort::OneStop);
    port.setParity(QSerialPort::NoParity);
    port.setFlowControl(QSerialPort::NoFlowControl);

    QObject::connect(&port, &QSerialPort::readyRead,
                     [&port](){
        qDebug() << port.readAll();
    });

    QObject::connect(&port, &QSerialPort::bytesWritten,
                     [](qint64 bytes){
        qDebug() << bytes;
    });

    QObject::connect(&port, &QSerialPort::errorOccurred,
                     [](QSerialPort::SerialPortError error){
        qDebug() << error;
    });

    if (port.open(QSerialPort::ReadWrite)) {
        qDebug() << port.write("Test");
    }

    return a.exec();
}

結果発表

MSVC2017 と Qt 5.13.0 のリリースモードでサンプルコードをコンパイルして実行すると、次のような出力が得られます。

QSerialPort::NoError
4
4
"Test"

全く同じコードをMSVC2017でリリースモードでコンパイルすると、今度はQt 5.13.1で以下のような出力が得られます。

QSerialPort::NoError
4

port.write リターン 4 これは4バイトがシリアルポートに送信されることを意味しますが、実際には行われません。 bytesWritten は出力されず、データも読み出されない。

注意 シリアルモニタプログラムで、書き込んだデータを表示しているが、データがピンに到達していない。

Qt5.13.1で動作させるために、何らかの方法でコードを修正することは可能でしょうか?

解決方法は?

原因

検索 Qtバグトラッカー Qt 5.13.1 on WindowsでQSerialPortが動作しないというバグが複数あるようです。それらはすべて、以下のものと重複しています。 QTBUG-78086 へのリンクも含まれています。 修正に関するGerritのレビュー .

バグの説明から。

にデータを送信しても、readyReadという信号が発せられることはない。 シリアルポートに接続されたデバイスから メンバーbytesAvailableは 接続されているシリアルポートにデータが送信されていても0 デバイスを使用することができます。

基本的には、発光させるようにしている。 _q_notifyqwinoverlappedionotifier.cpp は、保留中の通知がない場合にのみ表示されます。残念なことに

<ブロッククオート

そのコミットは、Windows上のI/Oを完全に壊しています。

解決方法

今のところ、5.13.0 にダウングレードするか、Qt 5.13.2 を待つか、あるいは、Qt 5.13.3 を待つかの選択肢があります。

Qt 5.13.1 を修正する qserialport を自分自身で確認します。

  • オープン QTDIR\5.13.1\Src\qtserialport\qtserialport.pro QtCreatorで
  • (オプション)キットを選択する必要があるかもしれません、例. Projects -> Manage kits -> Desktop Qt 5.13.1 MSVC2017 64bit
  • をプロジェクトツリーで開きます。 src/serialport/serialport-lib/sources/qwinoverlappedionotifier.cpp
  • 削除 QAtomicInt pendingNotifications;
  • 変更

    if (!waiting && pendingNotifications-- == 0)
        emit q->_q_notify();
    
    

    になります。

    if (!waiting)
        emit q->_q_notify();
    
    
  • 変更

    int n = pendingNotifications.fetchAndStoreAcquire(0);
    while (--n >= 0) {
        if (WaitForSingleObject(hSemaphore, 0) == WAIT_OBJECT_0)
            dispatchNextIoResult();
    }
    
    

    になります。

    if (WaitForSingleObject(hSemaphore, 0) == WAIT_OBJECT_0)
        dispatchNextIoResult();
    
    
  • QtCreator では、次のようになります。 build -> clean all であれば run qmake では rebuild all

  • ビルドフォルダを探し、コピーして置き換えます。 Qt5SerialPort.dllQt5SerialPortd.dll から build\bin から QTDIR\5.13.1\msvc2017_64\bin

これで、あなたのコードは動作するはずです。