Qt多线程中定时读取Modbus服务器 寄存器以及读写,另一个线程点击刷新系统时间

版权声明:DfrY https://blog.csdn.net/dfy1407/article/details/88229807

ui界面

在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

程序结构图

在这里插入图片描述

global.h

#ifndef GLOBAL_H
#define GLOBAL_H
#include <QString>

class global
{
public:
    global();
    static QString ComPortName;
    static QString Tor;
};

#endif // GLOBAL_H

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "plctimerthread.h"
#include "plcthread.h"
#include <QTimer>
#include <QTime>
#include <QDebug>
#include <QString>
#include <QThread>
#include <QDebug>
#include "global.h"

#include <QModbusDataUnit>
#include <QModbusRtuSerialMaster>
#include <QModbusClient>
#include <QModbusReply>

#include <QSerialPort>
#include <QSerialPortInfo>


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();


private:
    Ui::MainWindow *ui;
    QThread *thread;
    PlcTimerThread *plcThread;

    QThread *qthreadPlc;
    PlcThread *plc;

signals:
    void sendSpinbox(int);
    void writeTor(QString);

private slots:
    void on_pushButton_clicked();
    void on_pushButton_2_clicked();
    void on_pushButton_3_clicked();
    void on_pushButton_4_clicked();
    void showTime(QString);
    void on_spinBox_valueChanged();
    void on_connectModbus_clicked();
    void on_searchPort_clicked();
    void on_writeT_clicked();

    void on_statusBar(const QString&);
    void on_change2Discon();
    void on_change2Con();
    void on_updateT(QString);
    void on_updateS(QString);




};

#endif // MAINWINDOW_H

plcthread.h

#ifndef PLCTHREAD_H
#define PLCTHREAD_H

#include <QObject>
#include <QModbusDataUnit>
#include <QModbusRtuSerialMaster>
#include <QModbusClient>
#include <QModbusReply>
#include <QSerialPort>
#include <QSerialPortInfo>
#include "global.h"
#include <QString>
#include <QDebug>
#include <QThread>
#include <QTimer>


class PlcThread : public QObject
{
    Q_OBJECT
public:
    explicit PlcThread(QObject *parent = nullptr);
    ~PlcThread();

    void doWork();
    void connectPlc();

    void readPlc();
    void torqReadReady();
    void spdReadReady();
    void on_writeTor(QString);

signals:
    void startWork();
    void finishWork();

    void statusBar(const QString&);
    void change2Discon();
    void change2Con();


    void updateT(QString);
    void updateS(QString);

public slots:

private:
    QModbusClient *modbusDevice;
    QTimer *dataTimer;
    uchar T[4];
    uchar S[4];

};

#endif // PLCTHREAD_H

plctimerthread.h

#ifndef PLCTIMERTHREAD_H
#define PLCTIMERTHREAD_H

#include <QObject>
#include <QTimer>
#include <QDebug>
#include <QTime>
#include <QString>
#include "ui_mainwindow.h"
#include <QMainWindow>

#include <QModbusDataUnit>
#include <QModbusRtuSerialMaster>
#include <QModbusClient>
#include <QModbusReply>

#include <QSerialPort>
#include <QSerialPortInfo>

class PlcTimerThread : public QObject
{
    Q_OBJECT
public:
    explicit PlcTimerThread(QObject *parent = nullptr);
    ~PlcTimerThread();
public:
    void run();
    void dowork();
    void printSpinBox(int);
signals:
    void workStart();
    void workFinished();
    void upDateTime(QString);
private:
    QTimer *timer;
    QString str_time;
    int spinbox;


public slots:





};

#endif // PLCTIMERTHREAD_H

global.cpp

#include "global.h"

QString global::ComPortName;
QString global::Tor;

global::global()
{

}

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "plctimerthread.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    plcThread = new PlcTimerThread();
    thread =new QThread();
    plcThread->moveToThread(thread);

    plc = new PlcThread;
    qthreadPlc =new QThread();
    plc->moveToThread(qthreadPlc);


/*********************/
//    connect(thread,&QThread::started,plcThread,&PlcTimerThread::run);
    connect(plcThread,&PlcTimerThread::workStart,plcThread,&PlcTimerThread::run);
    connect(plcThread,&PlcTimerThread::workFinished,thread,&QThread::quit);
    connect(thread,&QThread::finished,thread,&QThread::deleteLater);

    connect(plcThread,&PlcTimerThread::upDateTime,this,&MainWindow::showTime);

    connect(this,&MainWindow::sendSpinbox,plcThread,&PlcTimerThread::printSpinBox);


    thread->start();
    qDebug()<<"开启线程";
    /*******x线程2******/
    connect(qthreadPlc,&QThread::started,plc,&PlcThread::doWork);
    connect(plc,&PlcThread::startWork,plc,&PlcThread::connectPlc);
    connect(plc,&PlcThread::finishWork,qthreadPlc,&QThread::quit);
    connect(qthreadPlc,&QThread::finished,qthreadPlc,&QThread::deleteLater);

    connect(plc,&PlcThread::statusBar,this,&MainWindow::on_statusBar);
    connect(plc,&PlcThread::change2Con,this,&MainWindow::on_change2Con);
    connect(plc,&PlcThread::change2Discon,this,&MainWindow::on_change2Discon);
    connect(plc,&PlcThread::updateT,this,&MainWindow::on_updateT);
    connect(plc,&PlcThread::updateS,this,&MainWindow::on_updateS);
    connect(this,&MainWindow::writeTor,plc,&PlcThread::on_writeTor);
    qthreadPlc->start();

}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()//start
{
    qDebug()<<"主线程ID:"<<QThread::currentThread();
    emit plcThread->workStart();
}

void MainWindow::on_pushButton_2_clicked()
{
    qDebug()<<"主线程ID:"<<QThread::currentThread();  //显示当前线程的数值
}

void MainWindow::on_pushButton_3_clicked()//进入线程
{
    plcThread = new PlcTimerThread();
    thread =new QThread();
    plcThread->moveToThread(thread);

//    connect(thread,&QThread::started,plcThread,&PlcTimerThread::run);
    connect(plcThread,&PlcTimerThread::workStart,plcThread,&PlcTimerThread::run);
    connect(this,&MainWindow::destroyed,plcThread,&PlcTimerThread::workFinished);
    connect(plcThread,&PlcTimerThread::workFinished,thread,&QThread::quit);
    connect(thread,&QThread::finished,thread,&QThread::deleteLater);

    connect(plcThread,&PlcTimerThread::upDateTime,this,&MainWindow::showTime);



    thread->start();
    qDebug()<<"开启线程";

}

void MainWindow::on_pushButton_4_clicked()//退出线程
{
    emit plcThread->workFinished();
    qDebug()<<"退出线程";
}
//    thread->quit();

void MainWindow::showTime(QString time)
{
    ui->lineEdit->setText(time);
}

void MainWindow::on_spinBox_valueChanged()
{
    qDebug()<<"changed";
    emit sendSpinbox(ui->spinBox->value());
}

void MainWindow::on_connectModbus_clicked()
{
    global::ComPortName = ui->serialBox->currentText();
    emit plc->startWork();
    qDebug()<<"click con";
}

void MainWindow::on_searchPort_clicked()
{
    ui->serialBox->clear();
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        ui->serialBox->addItem(info.portName());
    }

}

void MainWindow::on_writeT_clicked()
{
    QString str1 = ui->torque->text();

    QByteArray str2 = QByteArray::fromHex (str1.toLatin1().data());
    global::Tor = str2.toHex().data();
    qDebug()<<global::Tor;
    emit writeTor(global::Tor);
}

void MainWindow::on_statusBar(const QString &message)
{
    statusBar()->showMessage(message,5000);

}

void MainWindow::on_change2Discon()
{
    ui->connectModbus->setText("disconnectModbus");
}

void MainWindow::on_change2Con()
{
    ui->connectModbus->setText("connectModbus");

}

void MainWindow::on_updateT(QString t)
{
    ui->readT->setText(t);
}

void MainWindow::on_updateS(QString s)
{
    ui->readS->setText(s);
}


plcthread.cpp

#include "plcthread.h"
#include <QSerialPort>
#include <QSerialPortInfo>

PlcThread::PlcThread(QObject *parent) : QObject(parent)
{

}

PlcThread::~PlcThread()
{

}

void PlcThread::doWork()
{
  modbusDevice = new QModbusRtuSerialMaster;
  dataTimer = new QTimer;
  connect(dataTimer,&QTimer::timeout,this,&PlcThread::readPlc);
}

void PlcThread::connectPlc()
{
    qDebug()<<"connect";
    qDebug()<<"显示plc线程ID:"<<QThread::currentThread();  //显示当前线程的数值


    if(!modbusDevice)
    {
        return;
    }
//    statusBar()->clearMessage();
    if(modbusDevice->state() != QModbusDevice::ConnectedState)
    {

        modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,global::ComPortName);
        modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,QSerialPort::EvenParity);
        modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,QSerialPort::Baud9600);
        modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,QSerialPort::Data8);
        modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,QSerialPort::OneStop);
        modbusDevice->setTimeout(1000);
        modbusDevice->setNumberOfRetries(3);

        if(!modbusDevice->connectDevice())//连接失败
        {
            //statusBar()->showMessage(tr("Connect Failed:") + modbusDevice->errorString(),5000);
            emit statusBar(tr("Connect Failed:") + modbusDevice->errorString());
        }
        else//成功连接
        {
            emit change2Discon();
            dataTimer->start(500);
        }
    }
    else
    {
        modbusDevice->disconnectDevice();
        dataTimer->stop();
        emit change2Con();
    }
    qDebug() << modbusDevice->state();

}

void PlcThread::readPlc()
{
    qDebug()<<"read";
    if (!modbusDevice)
    {
        return;
    }
    //statusBar()->clearMessage();
    emit statusBar(nullptr);
    QModbusDataUnit readUnit = QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 0, 2);
    if (auto *reply = modbusDevice->sendReadRequest(readUnit, 1)) //1->modbus设备地址
    {
        if (!reply->isFinished())
        {
            connect(reply, &QModbusReply::finished, this, &PlcThread::torqReadReady);
        }
        else
        {
            delete reply; // broadcast replies return immediately
        }
    }
    else
    {
        //statusBar()->showMessage(tr("Read error: ") + modbusDevice->errorString(), 5000);
        emit statusBar(tr("Read error: ") + modbusDevice->errorString());
    }
    /**/
    QModbusDataUnit readUnit2 = QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 2, 2);
    if (auto *reply = modbusDevice->sendReadRequest(readUnit2, 1)) //1->modbus设备地址
    {
        if (!reply->isFinished())
        {
            connect(reply, &QModbusReply::finished, this, &PlcThread::spdReadReady);
        }
        else
        {
            delete reply; // broadcast replies return immediately
        }
    }
    else
    {
        //statusBar()->showMessage(tr("Read error: ") + modbusDevice->errorString(), 5000);
        emit statusBar(tr("Read error: ") + modbusDevice->errorString());
    }


}

void PlcThread::torqReadReady()
{
    auto reply = qobject_cast<QModbusReply *>(sender());
    if (!reply)
    {
        return;
    }

    if (reply->error() == QModbusDevice::NoError)
    {
        const QModbusDataUnit unit = reply->result();
        for (uint i = 0; i < unit.valueCount(); i++)
        {
            int ii = static_cast<int>(i);
            QString str =QString("%1").arg(unit.value(ii),4,16,QLatin1Char('0'));
            qDebug()<<str;
            bool ok;
            T[3-2*ii]= static_cast<uchar>(str.mid(0,2).toInt(&ok,16));
            T[2-2*ii]= static_cast<uchar>(str.mid(2,4).toInt(&ok,16));
        }

        float f_T;
        memcpy_s(&f_T , sizeof(float) , T , 4);
        qDebug()<<f_T;

        //ui->readT->setText(QString::number(static_cast<double>(f_T) ));

        emit updateT(QString::number(static_cast<double>(f_T) ));
    }
    else if (reply->error() == QModbusDevice::ProtocolError)
    {
//        statusBar()->showMessage(tr("Read response error: %1 (Mobus exception: 0x%2)").
//                                    arg(reply->errorString()).
//                                    arg(reply->rawResult().exceptionCode(), -1, 16), 5000);
        emit statusBar(tr("Read response error: %1 (Mobus exception: 0x%2)").
                       arg(reply->errorString()).
                       arg(reply->rawResult().exceptionCode(), -1, 16));
    }
    else
    {
//        statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)").
//                                    arg(reply->errorString()).
//                                    arg(reply->error(), -1, 16), 5000);
        emit statusBar(tr("Read response error: %1 (code: 0x%2)").
                       arg(reply->errorString()).
                       arg(reply->error(), -1, 16));
    }

    reply->deleteLater();

}

void PlcThread::spdReadReady()
{
    auto reply2 = qobject_cast<QModbusReply *>(sender());
    if (!reply2)
    {
        return;
    }

    if (reply2->error() == QModbusDevice::NoError)
    {
        const QModbusDataUnit unit = reply2->result();
        for (uint i = 0; i < unit.valueCount(); i++)
        {
            int ii = static_cast<int>(i);
            QString str =QString("%1").arg(unit.value(ii),4,16,QLatin1Char('0'));
            qDebug()<<str;
            bool ok;
            S[3-2*ii]= static_cast<uchar>(str.mid(0,2).toInt(&ok,16));
            S[2-2*ii]= static_cast<uchar>(str.mid(2,4).toInt(&ok,16));
        }

        float f_S;
        memcpy_s(&f_S , sizeof(float) , S , 4);
        qDebug()<<f_S;

       // ui->readS->setText(QString::number(static_cast<double>(f_S) ));
        emit updateS(QString::number(static_cast<double>(f_S) ));
    }
    else if (reply2->error() == QModbusDevice::ProtocolError)
    {
//        statusBar()->showMessage(tr("Read response error: %1 (Mobus exception: 0x%2)").
//                                    arg(reply2->errorString()).
//                                    arg(reply2->rawResult().exceptionCode(), -1, 16), 5000);
        emit statusBar(tr("Read response error: %1 (Mobus exception: 0x%2)").
                       arg(reply2->errorString()).
                       arg(reply2->rawResult().exceptionCode(), -1, 16));

    }
    else
    {
//        statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)").
//                                    arg(reply2->errorString()).
//                                    arg(reply2->error(), -1, 16), 5000);
        emit statusBar(tr("Read response error: %1 (code: 0x%2)").
                       arg(reply2->errorString()).
                       arg(reply2->error(), -1, 16));

    }

    reply2->deleteLater();

}

void PlcThread::on_writeTor(QString t)
{
    if (!modbusDevice)
        return;
    //statusBar()->clearMessage();
    emit statusBar(nullptr);

    //QModbusDataUnit的参数::QModbusDataUnit(QModbusDataUnit::HoldingRegisters, startAddress, numberOfEntries)
    QModbusDataUnit writeUnit = QModbusDataUnit(QModbusDataUnit::HoldingRegisters, 4, 2);
    for (uint i = 0; i < writeUnit.valueCount(); i++)
    {
        int ii = static_cast<int>(i);
        //writeUnit.setValue(ii, holdingRegisters[ii + writeUnit.startAddress()]);
        int j = 4*ii;
        QString st = t.mid (j,4);
        bool ok;
        int hex =st.toInt(&ok,16);//将textedit中读取到的数据转换为16进制发送
        quint16 qhex =static_cast<quint16>(hex);
       // qDebug()<<writeUnit.valueCount();
        writeUnit.setValue(ii,qhex);

    }

    if (auto *reply = modbusDevice->sendWriteRequest(writeUnit, 1)) {//1->modbus 地址
        if (!reply->isFinished()) {
            connect(reply, &QModbusReply::finished, this, [this, reply]() {
                if (reply->error() == QModbusDevice::ProtocolError)
                {
//                    statusBar()->showMessage(tr("Write response error: %1 (Mobus exception: 0x%2)")
//                        .arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16),
//                        5000);
                    emit statusBar(tr("Write response error: %1 (Mobus exception: 0x%2)")
                                                          .arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16));
                } else if (reply->error() != QModbusDevice::NoError)
                {
//                    statusBar()->showMessage(tr("Write response error: %1 (code: 0x%2)").
//                        arg(reply->errorString()).arg(reply->error(), -1, 16), 5000);
                    emit statusBar(tr("Write response error: %1 (code: 0x%2)").
                                                  arg(reply->errorString()).arg(reply->error(), -1, 16));
                }
                reply->deleteLater();
            });
        } else {
            // broadcast replies return immediately
            reply->deleteLater();
        }
    } else {
        //statusBar()->showMessage(tr("Write error: ") + modbusDevice->errorString(), 5000);
        emit statusBar(tr("Write error: ") + modbusDevice->errorString());
    }

}

plctimerthread.cpp

#include "plctimerthread.h"
#include <QThread>

//static int timerCount = 0;

PlcTimerThread::PlcTimerThread(QObject *parent) : QObject(parent)
{

}

PlcTimerThread::~PlcTimerThread()
{

}

void PlcTimerThread::run()
{
//    emit workStart();
//    timer = new QTimer(this);
//    connect(timer,&QTimer::timeout,this,&PlcTimerThread::dowork);
//    timer->start(1000);
    qDebug()<<"run";
    dowork();
}

void PlcTimerThread::dowork()
{
//    timerCount ++;
//    if (timerCount > 100)
//    {
//        emit workFinished();
//    }

    //qDebug()<<QTime::currentTime()<<endl;
    qDebug()<<"显示时间线程ID:"<<QThread::currentThread();  //显示当前线程的数值
    QDateTime time = QDateTime::currentDateTime();
    str_time = time.toString("yyyy-MM-dd hh:mm:ss dddd");
    emit upDateTime(str_time);


}

void PlcTimerThread::printSpinBox(int spin)
{
    spinbox = spin;
    qDebug()<<"changed"<<spin;
    qDebug()<<"线程ID:"<<QThread::currentThread();  //显示当前线程的数值
}


运行效果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/dfy1407/article/details/88229807