Qt modbus通讯写上位

编程知识 更新时间:2023-05-02 19:12:58

Qt modbus通讯写上位

继上次PLC展厅,通过北辰网关的转Modbus功能,使用Qt写一个简单的S7-300的上位程序,可以查看正转时间,反转时间,还可以控制电机启停。

北辰网关设置

北辰网关的设置可以参考这篇文章西门子PLC实现modbusTCP通讯
我的设置如下图:

UI界面

计时器的实现

构造函数中

timer1 = new QTimer(this);  //timer1为QTimer类型
connect(timer1, SIGNAL(timeout()), this, SLOT(showTime()));
timer1->start(1000);

showTime()中

 time=time.addSecs(60);//time为QTime类型
 QString text = time.toString("hh:mm");
 if ((time.second() % 2) == 0)
        text[2] = ' ';
 ui->lcdNumber->display(text);

Modbus通讯

modbus通讯可以参考我之前的文章QModbusClient

QObject::sender()

因为有正转时间,反转时间,停止时间三个时间需要计时

 connect(timer1, SIGNAL(timeout()), this, SLOT(showTime()));
 connect(timer2, SIGNAL(timeout()), this, SLOT(showTime()));
 connect(timer3, SIGNAL(timeout()), this, SLOT(showTime()));

它们都连接到槽showTime();因此,需要在showTime()中判断是哪个对象发出了timeout()信号,这个是通过QObject::sender()来实现的。
在showTime()中

 QTimer *t=qobject_cast<QTimer *>(sender());
 if(t==timer1)
        ui->lcdNumber->display(text);
    else if (t==timer2)
        ui->lcdNumber_2->display(text);
    else
        ui->lcdNumber_3->display(text);

控制电机启停

因为通过北辰的网关没有读出M区的变量,采取通过控制DB块来控制电机启停。
修改PLC起保停程序如下:

I0.0和I0.1是通过PLC按钮启停。在Qt上位中可以向DB3.DBX0.0写入1和0来控制PLC启停。为什么是DB3,因为在北辰网关的设置中,ModbusTcp映射DB号为3

源程序

mymodbus.h

#ifndef MYMODBUS_H
#define MYMODBUS_H

#include <QWidget>
#include <QLCDNumber>
#include <QModbusDataUnit>
#include <QTimer>
#include <QTime>
#include <QModbusTcpClient>
#include <QDebug>

class ModbusRly;
class QModbusTcpClient;


namespace Ui {
class MyModbus;
}

class MyModbus : public QWidget
{
    Q_OBJECT

public:
    explicit MyModbus(QWidget *parent = 0);
    ~MyModbus();

private:

    QModbusTcpClient *client;
    QTime time;
    QString entry[5];
    QTimer *timer1;
    QTimer *timer2;
    QTimer *timer3;
    Ui::MyModbus *ui;

public slots:
    void showTime();

private slots:
    void on_pushButton_clicked();
    void on_pushButton_2_clicked();
    void readReady();
    void on_pushButton_3_clicked();
    void on_pushButton_4_clicked();
    void on_pushButton_5_clicked();
};

#endif // MYMODBUS_H

mymodbus.cpp

#include "mymodbus.h"
#include "ui_mymodbus.h"

MyModbus::MyModbus(QWidget *parent) :
    QWidget(parent),client(nullptr),time(QTime(0,0,0)),
    ui(new Ui::MyModbus)
{

    ui->setupUi(this);
    ui->pushButton_2->setEnabled(false);
    ui->pushButton_5->setEnabled(false);
    ui->pushButton_3->setEnabled(false);
    ui->pushButton_4->setEnabled(false);
    timer1 = new QTimer(this);
    timer2=new QTimer(this);
    timer3=new QTimer(this);
    connect(timer1, SIGNAL(timeout()), this, SLOT(showTime()));
    connect(timer2, SIGNAL(timeout()), this, SLOT(showTime()));
    connect(timer3, SIGNAL(timeout()), this, SLOT(showTime()));
    if (ui->lineEdit->text().isEmpty())
        ui->lineEdit->setText(QLatin1Literal("192.168.1.99"));

}
void MyModbus::showTime()
{
    QTimer *t=qobject_cast<QTimer *>(sender());
    on_pushButton_2_clicked();
    time=time.addSecs(60);

    QString text = time.toString("hh:mm");
    if ((time.second() % 2) == 0)
        text[2] = ' ';
    if(t==timer1)
        ui->lcdNumber->display(text);
    else if (t==timer2)
        ui->lcdNumber_2->display(text);
    //else
      //  ui->lcdNumber_3->display(text);
}
MyModbus::~MyModbus()
{
    delete client;
    delete ui;
}

void MyModbus::on_pushButton_clicked()
{
    client=new QModbusTcpClient(this);
    client->setConnectionParameter(QModbusDevice::NetworkAddressParameter,ui->lineEdit->text());
    client->setConnectionParameter(QModbusDevice::NetworkPortParameter, 502);
    if(!client->connectDevice())
    {
        qDebug("failed");
    }
    else
    {
        qDebug("successed");
        ui->pushButton_2->setEnabled(true);
        ui->pushButton_5->setEnabled(true);
        ui->pushButton_3->setEnabled(true);
        ui->pushButton_4->setEnabled(true);
    }


}

void MyModbus::on_pushButton_2_clicked()
{
    if(!client)
        return;
    QModbusDataUnit readUnit(QModbusDataUnit::Coils, 00000, 5);


    if (auto *reply = client->sendReadRequest(readUnit, 2)) // client id 255
    {
        if (!reply->isFinished())
        {
            // connect the finished signal of the request to your read slot
            connect(reply, &QModbusReply::finished, this, &MyModbus::readReady);

        }
        else
        {
            delete reply; // broadcast replies return immediately
            qDebug("delete reply");
        }
    }
    else
    {
       qDebug("request error"); // request error
    }
}

void MyModbus::readReady()
{
    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++) {
        entry[i] = QString::number(unit.value(i),
                                          unit.registerType() <= QModbusDataUnit::Coils ? 10 : 16);
        qDebug()<<i<<entry[i];
        }
     if(entry[3].toInt()==1&&entry[2].toInt()==1)
     {
        timer1->start(1000);
        timer2->stop();
        timer3->stop();

     }

     else if(entry[3].toInt()==0&&entry[2].toInt()==1)
     {
        timer2->start(1000);
        timer1->stop();
        timer3->stop();

     }
     else if(entry[2].toInt()==0)
     {
         timer1->stop();
         timer2->stop();
         timer3->start(1000);
         time.setHMS(0,0,0);
     }


    }
    reply->deleteLater();
}

void MyModbus::on_pushButton_3_clicked()
{
    if(!client)
        return;
    QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters, 0, 1); // write 1 value in address 30000
    writeUnit.setValue(0,256);
    if (auto *reply = client->sendWriteRequest(writeUnit, 2))
    {
        if (!reply->isFinished())
        {
            connect(reply, &QModbusReply::finished, this, [this, reply]()
            {
                if (reply->error() != QModbusDevice::NoError)
                        // error in reply
                    qDebug("No Error");
                    reply->deleteLater();
                });
        }
        else
        {
            if (reply->error() != QModbusDevice::NoError)
                // error in reply
            qDebug("No Error1");
            // broadcast replies return immediately
            reply->deleteLater();
        }
    }
    else
    {
        // error in request
    }
}

void MyModbus::on_pushButton_4_clicked()
{
    if(!client)
        return;
    QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters, 0, 1); // write 1 value in address 30001
    writeUnit.setValue(0,0);
    if (auto *reply = client->sendWriteRequest(writeUnit, 2))
    {
        if (!reply->isFinished())
        {
            connect(reply, &QModbusReply::finished, this, [this, reply]()
            {
                if (reply->error() != QModbusDevice::NoError)
                        // error in reply
                    qDebug("No Error");
                    reply->deleteLater();
                });
        }
        else
        {
            if (reply->error() != QModbusDevice::NoError)
                // error in reply

            // broadcast replies return immediately
            reply->deleteLater();
        }
    }
    else
    {
        // error in request
    }
}

void MyModbus::on_pushButton_5_clicked()
{
     client->disconnectDevice();
     ui->pushButton_5->setEnabled(false);
     ui->pushButton_2->setEnabled(false);
     ui->pushButton_3->setEnabled(false);
     ui->pushButton_4->setEnabled(false);
     timer1->stop();
     timer2->stop();
     timer3->stop();

}

main.cpp

#include "mymodbus.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyModbus w;
    w.show();

    return a.exec();
}

更多推荐

Qt modbus通讯写上位

本文发布于:2023-04-28 05:08:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/37d8917d118366d3ab649f2b41d3a330.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:上位   通讯   Qt   modbus

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!

  • 107803文章数
  • 27247阅读数
  • 0评论数