Как заставить работать QSerialPort из Qt5.13.1? - PullRequest
2 голосов
/ 20 сентября 2019

Проблема

QSerialPort из версии 5.13.1 библиотеки Qt физически не выводит данные под Windows 7 и 10.

Пример

Для демонстрацииОписанная проблема Я подготовил следующую настройку:

  1. Аппаратное обеспечение

Я проверил соединение между ПК с физическим последовательным портом (COM1) и реальным последовательным устройством, но в демонстрационных целях я создал простой шлейф, соединив контакты 2 и 3 разъема DSub ПК, т.е. Tx и Rx.

Программное обеспечение

Проблема возникает в моих собственных приложениях с графическим интерфейсом, а также в официальных примерах, поставляемых с 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 Ответ

2 голосов
/ 20 сентября 2019

Причина

Поиск Отслеживание ошибок Qt Кажется, есть несколько ошибок, связанных с тем, что QSerialPort не работает на Qt 5.13.1 в Windows.Все они дублируются с QTBUG-78086 , который также содержит ссылку на Обзор исправления Gerrit .

Из описания ошибки:

Сигнал readyRead никогда не излучается, даже если данные отправляются на последовательный порт с подключенного устройства.Элемент bytesAvailable возвращает 0, даже если данные были отправлены на последовательный порт с подключенного устройства.

По сути, они пытались передать _q_notify в qwinoverlappedionotifier.cpp, только если нет ожидающих уведомлений.К сожалению,

Этот коммит полностью нарушает ввод / вывод в Windows.

Решение

На данный момент у вас есть варианты понижения до 5.13.0,дождитесь Qt 5.13.2 или

Исправьте Qt 5.13.1 qserialport самостоятельно:

  • open 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
  • delete 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

Ваш код должен работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...