如何使 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
:
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.dll
和Qt5SerialPortd.dll
从build\bin
复制并替换为QTDIR\5.13.1\msvc2017_64\bin
您的代码现在应该可以工作了。
【讨论】:
太棒了!这样可行。非常感谢你!顺便说一句,我允许自己编辑您的答案,详细说明原因和解决方案,以便让其他想要自己解决这个问题的人更容易。以上是关于如何使 Qt5.13.1 中的 QSerialPort 工作?的主要内容,如果未能解决你的问题,请参考以下文章