如何使Qt5.13.1的QSerialPort工作?

sco*_*nov 6 c++ windows qt qt5

问题

QSerialPort 从Qt库的5.13.1版本开始,在Windows 7和10下不会实际输出数据。

为了演示所描述的问题,我准备了以下设置:

  1. 硬件

我已经测试了具有物理串行端口(COM1)的PC和实际串行设备之间的连接,但是出于演示目的,我通过将PC的DSub连接器的针脚2和3(即Tx和Tx)连接在一起创建了一个简单的环回接收

  1. 软件

问题发生在我自己的GUI应用程序以及Qt附带的官方示例中。但是,为了演示,我编写了一个非常基本的控制台应用程序:

SerialBug.pro

QT -= gui
QT += serialport

CONFIG += console

SOURCES += \
        main.cpp
Run Code Online (Sandbox Code Playgroud)

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();
}
Run Code Online (Sandbox Code Playgroud)

结果

在发布模式下使用MSVC2017和Qt 5.13.0编译并运行示例代码,将产生以下输出:

QSerialPort::NoError
4
4
"Test"
Run Code Online (Sandbox Code Playgroud)

使用MSVC2017在发布模式下编译的代码完全相同,但是这次使用Qt 5.13.1编译,产生以下输出:

QSerialPort::NoError
4
Run Code Online (Sandbox Code Playgroud)

port.write返回4,表示将4个字节发送到串行端口,但这实际上并未完成。bytesWritten不会发出并且不会回读数据。

注意:串行监视器程序正在显示写入的数据,但是数据未到达引脚。

是否有可能以任何方式修复代码以使其与Qt5.13.1一起使用?

tal*_*aki 6

原因

搜索Qt错误跟踪器时,似乎有多个关于QSerialPort无法在Windows上的Qt 5.13.1上运行的错误。所有这些都与QTBUG-78086重复,其中还包含Gerrit对该修复程序进行审查的链接。

从错误描述:

即使将数据从连接的设备发送到串行端口,也不会发出readyRead信号。即使已从连接的设备将数据发送到串行端口,成员bytesAvailable也会返回0。

基本上,他们试图发出_q_notifyqwinoverlappedionotifier.cpp仅如果没有通知待定。不幸地

该提交完全破坏了Windows上的I / O。

目前,您可以选择降级到5.13.0,等待Qt 5.13.2或

qserialport自己修复Qt 5.13.1 :

  • 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();
    
    Run Code Online (Sandbox Code Playgroud)

    if (!waiting)
        emit q->_q_notify();
    
    Run Code Online (Sandbox Code Playgroud)
  • 更改

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

    if (WaitForSingleObject(hSemaphore, 0) == WAIT_OBJECT_0)
        dispatchNextIoResult();
    
    Run Code Online (Sandbox Code Playgroud)
  • 在QtCreator中,转到build-> clean all,然后是run qmake,然后rebuild all

  • 找到build文件夹,然后复制和替代Qt5SerialPort.dll,并Qt5SerialPortd.dllbuild\binQTDIR\5.13.1\msvc2017_64\bin

您的代码现在应该可以工作了。