如何使 Qt5.13.1 中的 QSerialPort 工作?

Posted

技术标签:

【中文标题】如何使 Qt5.13.1 中的 QSerialPort 工作?【英文标题】:How to make QSerialPort from Qt5.13.1 work? 【发布时间】:2019-09-20 01:30:15 【问题描述】:

问题

QSerialPort 来自 Qt 库的 5.13.1 版本,在 Windows 7 和 10 下不会物理输出数据。

示例

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

    硬件

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

    软件

这个问题出现在我自己的 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 一起使用?

【问题讨论】:

【参考方案1】:

原因

搜索 Qt bug tracker 似乎存在多个关于 QSerialPort 无法在 Windows 上的 Qt 5.13.1 上运行的错误。所有这些都与QTBUG-78086 重复,其中还包含指向Gerrit review of the fix 的链接。

来自错误描述:

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

基本上,只有在没有待处理通知的情况下,他们才会尝试在qwinoverlappedionotifier.cpp 中发出_q_notify。可惜了

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

解决方案

现在您可以选择降级到 5.13.0,等待 Qt 5.13.2 或

自己修复 Qt 5.13.1 qserialport

用 QtCreator 打开QTDIR\5.13.1\Src\qtserialport\qtserialport.pro (可选)您可能需要选择一个套件,例如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.dllbuild\bin复制并替换为QTDIR\5.13.1\msvc2017_64\bin

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

【讨论】:

太棒了!这样可行。非常感谢你!顺便说一句,我允许自己编辑您的答案,详细说明原因和解决方案,以便让其他想要自己解决这个问题的人更容易。

以上是关于如何使 Qt5.13.1 中的 QSerialPort 工作?的主要内容,如果未能解决你的问题,请参考以下文章

带有WinRT C ++构建问题的Qt

VTK读取图片,然后QT显示

Qt 与 WinRT C++ 构建问题

C++内存管理18_总结_从最基础到最复杂

imageview中的Recryler如何使不可见

如何使 QStandardItemModel 中的图标居中?