Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QtSerialport blockingslave Example with Mainwindow class .



  • i am using the blocking example to communicate with micro controller with Mainwindow class instead of dialog to send and receive data any time from micro-controller without block receiving data from GUI
    so i redesign but this error is appear ,

    ASSERT failure in QMutexLocker: "QMutex pointer is misaligned", file C:\Qt\5.13.1\mingw73_64\include\QtCore/qmutex.h, line 202
    20:28:09: The program has unexpectedly finished.
    

    //mainwindow.h
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include "slavethread.h"
    #include <QMainWindow>
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    private:
        Ui::MainWindow *ui;
        SlaveThread *m_thread ;
    };
    #endif // MAINWINDOW_H
    
    

    //slavethread.h
    #ifndef SLAVETHREAD_H
    #define SLAVETHREAD_H
    
    #include <QMutex>
    #include <QThread>
    #include <QWaitCondition>
    
    class SlaveThread : public QThread
    {
        Q_OBJECT
    public:
        explicit SlaveThread(QObject *parent = nullptr);
        ~SlaveThread();
        void startSlave(const QString &portName, int waitTimeout, const QString &response);
    signals:
        void request(const QString &s);
        void error(const QString &s);
        void timeout(const QString &s);
    
    private:
        void run() override;
    
        QString m_portName;
        QString m_response;
        int m_waitTimeout = 0;
        QMutex m_mutex;
        bool m_quit = false;
    };
    
    #endif // SLAVETHREAD_H
    
    

    //mainwindow.cpp
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        m_thread->startSlave("COM15",10000,"HI");
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    

    //slavethread.cpp
    #include "slavethread.h"
    #include <QSerialPort>
    #include <QTime>
    #include <QDebug>
    
    SlaveThread::SlaveThread(QObject *parent) :
        QThread(parent)
    {
    
    }
    
    SlaveThread::~SlaveThread()
    {
        m_mutex.lock();
        m_quit = true;
        m_mutex.unlock();
        QThread::wait();
    }
    
    void SlaveThread::startSlave(const QString &portName, int waitTimeout, const QString &response)
    {
    
        const QMutexLocker locker(&m_mutex);
        m_portName = portName;
        m_waitTimeout = waitTimeout;
        m_response = response;
    
        if (!QThread::isRunning())
            QThread::start();
    }
    
    void SlaveThread::run()
    {
        bool currentPortNameChanged = false;
    
        m_mutex.lock();
    
        QString currentPortName;
        if (currentPortName != m_portName) {
            currentPortName = m_portName;
            currentPortNameChanged = true;
        }
    
        int currentWaitTimeout = m_waitTimeout;
        QString currentRespone = m_response;
        m_mutex.unlock();
    
        QSerialPort serial;
    
        while (!m_quit) {
    
            if (currentPortNameChanged) {
                serial.close();
                serial.setPortName(currentPortName);
    
                if (!serial.open(QIODevice::ReadWrite)) {
                    emit error(tr("Can't open %1, error code %2")
                               .arg(m_portName).arg(serial.error()));
                    return;
                }
            }
    
            if (serial.waitForReadyRead(currentWaitTimeout)) {
    
                // read request
                QByteArray requestData = serial.readAll();
                while (serial.waitForReadyRead(10))
                    requestData += serial.readAll();
    
                // write response
                const QByteArray responseData = currentRespone.toUtf8();
                serial.write(responseData);
                if (serial.waitForBytesWritten(m_waitTimeout)) {
                    const QString request = QString::fromUtf8(requestData);
                    emit this->request(request);
    
                } else {
                    emit timeout(tr("Wait write response timeout %1")
                                 .arg(QTime::currentTime().toString()));
                }
    
                qDebug() << "Data :" <<  requestData;
               qDebug() << "Sent :" <<  responseData;
    
            } else {
                emit timeout(tr("Wait read request timeout %1")
                             .arg(QTime::currentTime().toString()));
            }
    
            m_mutex.lock();
            if (currentPortName != m_portName) {
                currentPortName = m_portName;
                currentPortNameChanged = true;
            } else {
                currentPortNameChanged = false;
            }
            currentWaitTimeout = m_waitTimeout;
            currentRespone = m_response;
            m_mutex.unlock();
        }
    //! [13]
    }
    

  • Qt Champions 2020

    Don't use Qt 5.13.1, it has bugs.


  • Lifetime Qt Champion

    @Marco-Flad Threading is an advanced topic.

    Your problem can be solved with non-blocking serial communication, please use it and proper signal+slot handling.

    Regards



  • @aha_1980
    the signal and slots dosnt work with readyread() dosn't triggered if data available on serial its only triggered when i send data from qt to the connected device"and this data is old data " i tried with no solution the issue is her if you can have a look please ,

    https://forum.qt.io/topic/110038/qt-serial-port-not-receive-data-until-send-data-to-mc/5


  • Qt Champions 2020

    Don't use Qt 5.13.1, it has bugs.


  • Lifetime Qt Champion

    Hi @kuzulis,

    Are those bugs fixed in 5.14.0 for sure?

    Regards


  • Qt Champions 2020

    I'm think, yes.


Log in to reply