日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【Qt】modbus之TCP模式读操作

發(fā)布時(shí)間:2024/4/24 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Qt】modbus之TCP模式读操作 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

00. 目錄

文章目錄

    • 00. 目錄
    • 01. 概述
    • 02. 開發(fā)環(huán)境
    • 03. 讀Coils程序示例
    • 04. 讀DiscreteInputs程序示例
    • 05. 讀InputRegisters程序示例
    • 06. 讀HoldingRegisters程序示例
    • 07. 綜合示例
    • 08. 程序下載
    • 09. 附錄

01. 概述

Qt中幾個(gè)常用的串口modbus類

QModbusRtuSerialSlave //modbus串口通信方式下的服務(wù)器類 QModbusRtuSerialMaster //串口通信方式下的客戶端類 QModbusServer // QModbusServer類接收和處理modbus的請(qǐng)求。 QModbusDataUnit //存儲(chǔ)接收和發(fā)送數(shù)據(jù)的類,數(shù)據(jù)類型為1bit和16bit QModbusReply //客戶端訪問服務(wù)器后得到的回復(fù)(如客戶端讀服務(wù)器數(shù)據(jù)時(shí)包含數(shù)據(jù)信息)

02. 開發(fā)環(huán)境

Windows系統(tǒng):Windows10

Qt版本:Qt5.15或者Qt6

Pro配置文件如下

QT += core gui serialbus serialportgreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++11# You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0SOURCES += \main.cpp \widget.cppHEADERS += \widget.h# Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target

03. 讀Coils程序示例

widget.h文件

#ifndef WIDGET_H #define WIDGET_H#include <QWidget>//前向聲明 class QModbusClient; class QModbusReply;QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;QModbusClient *modbusDevice = nullptr;private slots:void onReadReady();void onModbusStateChanged(int state);void on_btnConnect_clicked();void on_btnCoil_clicked();void on_btnDiscreteInputs_clicked();void on_btnInputRegisters_clicked();void on_btnHoldingRegisters_clicked(); }; #endif // WIDGET_H

widget.cpp文件

#include "widget.h" #include "ui_widget.h" #include <QDebug> #include <QModbusTcpClient>//構(gòu)造函數(shù) Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//1. 創(chuàng)建QModbusDevice對(duì)象modbusDevice = new QModbusTcpClient(this);//禁用所有的讀操作ui->btnCoil->setEnabled(false);ui->btnDiscreteInputs->setEnabled(false);ui->btnHoldingRegisters->setEnabled(false);ui->btnInputRegisters->setEnabled(false);connect(modbusDevice, &QModbusClient::errorOccurred, [this](QModbusDevice::Error) {qDebug() << "new Error: " << modbusDevice->errorString();});if (nullptr == modbusDevice){qDebug() << "Cannot Create Modbus Client";}else{connect(modbusDevice, &QModbusClient::stateChanged,this, &Widget::onModbusStateChanged);}}//析構(gòu)函數(shù) Widget::~Widget() {if (modbusDevice){modbusDevice->disconnectDevice();}delete modbusDevice;delete ui; }void Widget::onReadReady() {auto reply = qobject_cast<QModbusReply*>(sender());if (nullptr == reply){return;}//判斷是否出錯(cuò)if (reply->error() == QModbusDevice::NoError){//讀取響應(yīng)數(shù)據(jù)const QModbusDataUnit responseData = reply->result();qDebug() << "讀到數(shù)據(jù)為:" << responseData.values();}else if (reply->error() == QModbusDevice::ProtocolError){qDebug() << "Read response Protocol error: " << reply->errorString();}else{qDebug() << "Read response Error: " << reply->errorString();}//刪除replyreply->deleteLater(); }void Widget::onModbusStateChanged(int state) {//判斷Modbus設(shè)備連接是否處于連接狀態(tài)if (state == QModbusDevice::UnconnectedState){qDebug() << "TCP Client連接到Server 未連接";ui->btnConnect->setText(tr("連接"));ui->btnCoil->setEnabled(false);ui->btnDiscreteInputs->setEnabled(false);ui->btnHoldingRegisters->setEnabled(false);ui->btnInputRegisters->setEnabled(false);}else if (state == QModbusDevice::ConnectingState){qDebug() << "TCP Client正在連接Server";}else if (state == QModbusDevice::ConnectedState){qDebug() << "TCP Client已經(jīng)連接到Server";ui->btnConnect->setText(tr("斷開連接"));ui->btnCoil->setEnabled(true);ui->btnDiscreteInputs->setEnabled(true);ui->btnHoldingRegisters->setEnabled(true);ui->btnInputRegisters->setEnabled(true);}else if (state == QModbusDevice::ClosingState){qDebug() << "設(shè)備已經(jīng)被關(guān)閉";} }//連接按鈕槽函數(shù) void Widget::on_btnConnect_clicked() {if (!modbusDevice){return;}if (modbusDevice->state() != QModbusDevice::ConnectedState){modbusDevice->setConnectionParameter(QModbusDevice::NetworkAddressParameter, "127.0.0.1");modbusDevice->setConnectionParameter(QModbusDevice::NetworkPortParameter, 10086);//設(shè)置超時(shí)時(shí)間modbusDevice->setTimeout(1000); //1秒//設(shè)置失敗重試次數(shù)modbusDevice->setNumberOfRetries(3);//連接到服務(wù)端bool ok = modbusDevice->connectDevice();if (!ok){qDebug() << "modbusDevice->connectDevice failed";}}else{//斷開連接modbusDevice->disconnectDevice();ui->btnConnect->setText(tr("連接"));ui->btnCoil->setEnabled(false);ui->btnDiscreteInputs->setEnabled(false);ui->btnHoldingRegisters->setEnabled(false);ui->btnInputRegisters->setEnabled(false);}}//讀線圈 void Widget::on_btnCoil_clicked() {//QModbusDataUnit::Coils 從地址0開始讀取10個(gè)線圈值QModbusDataUnit data(QModbusDataUnit::Coils, 0, 10);auto reply = modbusDevice->sendReadRequest(data, 0x1);if (nullptr == reply){qDebug() << "發(fā)送請(qǐng)求數(shù)據(jù)失敗: " << modbusDevice->errorString();}else{if (!reply->isFinished()){connect(reply, &QModbusReply::finished, this, &Widget::onReadReady);}else{//broadcast replies return immediatelydelete reply;}} }//讀離散輸入 void Widget::on_btnDiscreteInputs_clicked() {}//讀輸入寄存器 void Widget::on_btnInputRegisters_clicked() {}//讀保持寄存器 void Widget::on_btnHoldingRegisters_clicked() {}

執(zhí)行結(jié)果

15:18:15: Starting D:\ProgramData\Qt\build-Test1-Desktop_Qt_5_15_2_MinGW_32_bit-Debug\debug\Test1.exe ... TCP Client正在連接Server TCP Client已經(jīng)連接到Server 讀到數(shù)據(jù)為: QVector(0, 0, 1, 0, 0, 0, 1, 0, 1, 0) 設(shè)備已經(jīng)被關(guān)閉 TCP Client連接到Server 未連接 15:18:36: D:\ProgramData\Qt\build-Test1-Desktop_Qt_5_15_2_MinGW_32_bit-Debug\debug\Test1.exe exited with code 0

04. 讀DiscreteInputs程序示例

widget.h文件

#ifndef WIDGET_H #define WIDGET_H#include <QWidget>//前向聲明 class QModbusClient; class QModbusReply;QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;QModbusClient *modbusDevice = nullptr;private slots:void onReadReady();void onModbusStateChanged(int state);void on_btnConnect_clicked();void on_btnCoil_clicked();void on_btnDiscreteInputs_clicked();void on_btnInputRegisters_clicked();void on_btnHoldingRegisters_clicked(); }; #endif // WIDGET_H

widget.cpp文件

//讀離散輸入 void Widget::on_btnDiscreteInputs_clicked() {//QModbusDataUnit::DiscreteInputs 從地址0開始讀取10個(gè)離散輸入值QModbusDataUnit data(QModbusDataUnit::DiscreteInputs, 0, 10);auto reply = modbusDevice->sendReadRequest(data, 0x1);if (nullptr == reply){qDebug() << "發(fā)送請(qǐng)求數(shù)據(jù)失敗: " << modbusDevice->errorString();}else{if (!reply->isFinished()){connect(reply, &QModbusReply::finished, this, &Widget::onReadReady);}else{//broadcast replies return immediatelydelete reply;}} }

執(zhí)行結(jié)果

15:25:14: Starting D:\ProgramData\Qt\build-Test1-Desktop_Qt_5_15_2_MinGW_32_bit-Debug\debug\Test1.exe ... TCP Client正在連接Server TCP Client已經(jīng)連接到Server 讀到數(shù)據(jù)為: QVector(1, 1, 1, 1, 1, 0, 0, 0, 0, 0) 設(shè)備已經(jīng)被關(guān)閉 TCP Client連接到Server 未連接

05. 讀InputRegisters程序示例

widget.h文件

#ifndef WIDGET_H #define WIDGET_H#include <QWidget>//前向聲明 class QModbusClient; class QModbusReply;QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;QModbusClient *modbusDevice = nullptr;private slots:void onReadReady();void onModbusStateChanged(int state);void on_btnConnect_clicked();void on_btnCoil_clicked();void on_btnDiscreteInputs_clicked();void on_btnInputRegisters_clicked();void on_btnHoldingRegisters_clicked(); }; #endif // WIDGET_H

widget.cpp文件

//讀輸入寄存器 void Widget::on_btnInputRegisters_clicked() {//QModbusDataUnit::InputRegisters 從地址0開始讀取10個(gè)輸入寄存器的值QModbusDataUnit data(QModbusDataUnit::InputRegisters, 0, 10);auto reply = modbusDevice->sendReadRequest(data, 0x1);if (nullptr == reply){qDebug() << "發(fā)送請(qǐng)求數(shù)據(jù)失敗: " << modbusDevice->errorString();}else{if (!reply->isFinished()){connect(reply, &QModbusReply::finished, this, &Widget::onReadReady);}else{//broadcast replies return immediatelydelete reply;}} }

執(zhí)行結(jié)果

15:28:06: Starting D:\ProgramData\Qt\build-Test1-Desktop_Qt_5_15_2_MinGW_32_bit-Debug\debug\Test1.exe ... TCP Client正在連接Server TCP Client已經(jīng)連接到Server 讀到數(shù)據(jù)為: QVector(0, 12, 0, 11, 0, 0, 13, 0, 0, 0) 設(shè)備已經(jīng)被關(guān)閉 TCP Client連接到Server 未連接

06. 讀HoldingRegisters程序示例

widget.h文件

#ifndef WIDGET_H #define WIDGET_H#include <QWidget>//前向聲明 class QModbusClient; class QModbusReply;QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;QModbusClient *modbusDevice = nullptr;private slots:void onReadReady();void onModbusStateChanged(int state);void on_btnConnect_clicked();void on_btnCoil_clicked();void on_btnDiscreteInputs_clicked();void on_btnInputRegisters_clicked();void on_btnHoldingRegisters_clicked(); }; #endif // WIDGET_H

widget.cpp文件

//讀保持寄存器 void Widget::on_btnHoldingRegisters_clicked() {//從地址0開始讀取10個(gè)保持寄存器的值QModbusDataUnit data(QModbusDataUnit::HoldingRegisters, 0, 10);auto reply = modbusDevice->sendReadRequest(data, 0x1);if (nullptr == reply){qDebug() << "發(fā)送請(qǐng)求數(shù)據(jù)失敗: " << modbusDevice->errorString();}else{if (!reply->isFinished()){connect(reply, &QModbusReply::finished, this, &Widget::onReadReady);}else{//broadcast replies return immediatelydelete reply;}} }

執(zhí)行結(jié)果

15:29:35: Starting D:\ProgramData\Qt\build-Test1-Desktop_Qt_5_15_2_MinGW_32_bit-Debug\debug\Test1.exe ... TCP Client正在連接Server TCP Client已經(jīng)連接到Server 讀到數(shù)據(jù)為: QVector(0, 0, 11, 12, 13, 14, 15, 0, 0, 111) 設(shè)備已經(jīng)被關(guān)閉 TCP Client連接到Server 未連接

07. 綜合示例

程序界面

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-utd9gda4-1621496836516)(assets/image-20210520154331905.png)]

settingdialog.h文件

#ifndef SETTINGDIALOG_H #define SETTINGDIALOG_H#include <QDialog> #include <QtSerialPort>namespace Ui { class SettingDialog; }//串口設(shè)置相關(guān)類 class SettingDialog : public QDialog {Q_OBJECTpublic:struct Settings{//串口名QString serialName = "COM3";//校驗(yàn)位int parity = QSerialPort::NoParity;//波特率int baud = QSerialPort::Baud19200;//數(shù)據(jù)位int dataBits = QSerialPort::Data8;//停止位int stopBits = QSerialPort::OneStop;//響應(yīng)時(shí)間int responseTime = 1000;//重試次數(shù)int numberOfRetries = 3;};explicit SettingDialog(QWidget *parent = nullptr);~SettingDialog();//返回參數(shù)設(shè)置信息Settings settings() const;private slots:void on_btnApply_clicked();private:Ui::SettingDialog *ui;Settings m_settings; };#endif // SETTINGDIALOG_H

settingdialog.cpp文件

#include "settingdialog.h" #include "ui_settingdialog.h"//構(gòu)造函數(shù) SettingDialog::SettingDialog(QWidget *parent) :QDialog(parent),ui(new Ui::SettingDialog) {ui->setupUi(this);//設(shè)置默認(rèn)參數(shù)信息ui->serialNameLineEdit->setText(tr("COM3"));ui->parityComboBox->setCurrentIndex(0);ui->baudComboBox->setCurrentText(QString::number(m_settings.baud));ui->dataBitComboBox->setCurrentText(QString::number(m_settings.dataBits));ui->stopBitComboBox->setCurrentText(QString::number(m_settings.stopBits));ui->spinBoxTimeOut->setValue(m_settings.responseTime);ui->spinBoxRetry->setValue(m_settings.numberOfRetries);}//析構(gòu)函數(shù) SettingDialog::~SettingDialog() {delete ui; }//返回參數(shù)信息 SettingDialog::Settings SettingDialog::settings() const {return m_settings; }//引用按鈕槽函數(shù) void SettingDialog::on_btnApply_clicked() {m_settings.serialName = ui->serialNameLineEdit->text();m_settings.parity = ui->parityComboBox->currentText().toInt();m_settings.baud = ui->baudComboBox->currentText().toInt();m_settings.dataBits = ui->dataBitComboBox->currentText().toInt();m_settings.stopBits = ui->stopBitComboBox->currentText().toInt();m_settings.responseTime = ui->spinBoxTimeOut->value();m_settings.numberOfRetries = ui->spinBoxRetry->value();//隱藏參數(shù)設(shè)置對(duì)話框hide(); }

mainwindow.h文件

#ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QModbusDataUnit>QT_BEGIN_NAMESPACEnamespace Ui {class MainWindow; }class SettingDialog; class QModbusClient; class QModbusReply;QT_END_NAMESPACEclass MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();//信號(hào)與槽進(jìn)行關(guān)聯(lián)void initActions();//讀請(qǐng)求數(shù)據(jù)包封裝QModbusDataUnit readRequest() const;private slots:void onConnectButtonClicked();void onConnectTypeChanged(int);void onModbusStateChanged(int state);void onReadButtonClicked();void onReadReady();private:Ui::MainWindow *ui = nullptr;SettingDialog *m_settingDialog = nullptr;QModbusClient *modbusDevice = nullptr;QModbusReply *reply = nullptr;}; #endif // MAINWINDOW_H

mainwindow.cpp文件

#include "mainwindow.h" #include "ui_mainwindow.h" #include <QMessageBox> #include "settingdialog.h" #include <QModbusRtuSerialMaster> #include <QModbusReply> #include <QStandardItemModel> #include <QModbusDataUnit> #include <QModbusTcpClient>//連接類型枚舉變量 enum ModbusConnection {Serial,Tcp };MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);//創(chuàng)建對(duì)象m_settingDialog = new SettingDialog(this);//初始化信號(hào)與槽initActions();//創(chuàng)建寫模型writeModel = new WriteRegisterModel(this);writeModel->setStartAddress(ui->sbWriteStartAddr->value());writeModel->setNumberOfValues(ui->cbWriteCount->currentText());//MVCui->treeViewWrite->setModel(writeModel);//隱藏第二列ui->treeViewWrite->hideColumn(2);connect(writeModel, &WriteRegisterModel::updateViewport,ui->treeViewWrite->viewport(), QOverload<>::of(&QWidget::update));//默認(rèn)為串口連接方式ui->cbConnType->setCurrentIndex(0);onConnectTypeChanged(0);auto model = new QStandardItemModel(10, 1, this);for (int i = 0; i < 10; i++){model->setItem(i, new QStandardItem(QStringLiteral("%1").arg(i + 1)));}ui->cbWriteCount->setModel(model);ui->cbWriteCount->setCurrentText("10");connect(ui->cbWriteCount, &QComboBox::currentTextChanged,writeModel, &WriteRegisterModel::setNumberOfValues);auto valueChanged = QOverload<int>::of(&QSpinBox::valueChanged);connect(ui->sbWriteStartAddr, valueChanged, writeModel, &WriteRegisterModel::setStartAddress);connect(ui->sbWriteStartAddr, valueChanged, this, [this, model](int i){int lastIndex = 0;const int curIndex = ui->cbWriteCount->currentIndex();for (int j = 0; j < 10; j++){//設(shè)置使能if (j < (10 - i)){lastIndex = j;model->item(j)->setEnabled(true);}else{//設(shè)置禁用model->item(j)->setEnabled(false);}}if (curIndex > lastIndex){ui->cbWriteCount->setCurrentIndex(lastIndex);}}); }//析構(gòu)函數(shù) MainWindow::~MainWindow() {if (modbusDevice){modbusDevice->disconnectDevice();delete modbusDevice;}delete ui; }//信號(hào)與槽進(jìn)行關(guān)聯(lián)s void MainWindow::initActions() {//使能部分功能ui->actionConnect->setEnabled(true);ui->actionDisconnect->setEnabled(false);ui->actionQuit->setEnabled(true);ui->actionOption->setEnabled(true);//禁用讀寫操作ui->btnRead->setEnabled(false);ui->btnWrite->setEnabled(false);ui->btnReadWrite->setEnabled(false);//信號(hào)與槽關(guān)聯(lián)connect(ui->btnConnect, &QPushButton::clicked,this, &MainWindow::onConnectButtonClicked);connect(ui->actionConnect, &QAction::triggered,this, &MainWindow::onConnectButtonClicked);connect(ui->actionDisconnect, &QAction::triggered,this, &MainWindow::onConnectButtonClicked);//讀操作按鈕槽函數(shù)關(guān)聯(lián)connect(ui->btnRead, &QPushButton::clicked,this, &MainWindow::onReadButtonClicked);connect(ui->btnWrite, &QPushButton::clicked,this, &MainWindow::onWriteButtonClicked);connect(ui->btnReadWrite, &QPushButton::clicked,this, &MainWindow::onReadWriteButtonClicked);connect(ui->cbRegisterType, QOverload<int>::of(&QComboBox::currentIndexChanged),this, &MainWindow::onWriteTableChanged);connect(ui->cbConnType, QOverload<int>::of(&QComboBox::currentIndexChanged),this, &MainWindow::onConnectTypeChanged);//退出菜單connect(ui->actionQuit, &QAction::triggered, this, &MainWindow::close);//顯示參數(shù)設(shè)置對(duì)話框connect(ui->actionOption, &QAction::triggered, m_settingDialog, &QDialog::show);connect(ui->actionAbout, &QAction::triggered, [=]() {QMessageBox::aboutQt(this, "About Qt");}); }//構(gòu)建請(qǐng)求報(bào)文 QModbusDataUnit MainWindow::readRequest() const {//const auto type = static_cast<QModbusDataUnit::RegisterType>(ui->cbRegisterType->currentData().toInt());QModbusDataUnit::RegisterType type = QModbusDataUnit::Invalid;qDebug() << ui->cbRegisterType->currentText();if (ui->cbRegisterType->currentText() == QString("線圈")){type = QModbusDataUnit::Coils;}else if (ui->cbRegisterType->currentText() == QString("離散輸入")){type = QModbusDataUnit::DiscreteInputs;}else if (ui->cbRegisterType->currentText() == QString("輸入寄存器")){type = QModbusDataUnit::InputRegisters;}else if (ui->cbRegisterType->currentText() == QString("保持寄存器")){type = QModbusDataUnit::HoldingRegisters;}qDebug() << "請(qǐng)求報(bào)文類型: " << type;//獲取int startAddress = ui->spReadStartAddr->value();Q_ASSERT(startAddress >= 0 && startAddress < 10);quint16 numberOfEntries = ui->cbReadCount->currentText().toUShort();return QModbusDataUnit(type, startAddress, numberOfEntries); }//寫請(qǐng)求數(shù)據(jù)包封裝 QModbusDataUnit MainWindow::writeRequest() const {QModbusDataUnit::RegisterType type = QModbusDataUnit::Invalid;qDebug() << ui->cbRegisterType->currentText();if (ui->cbRegisterType->currentText() == QString("線圈")){type = QModbusDataUnit::Coils;}else if (ui->cbRegisterType->currentText() == QString("離散輸入")){type = QModbusDataUnit::DiscreteInputs;}else if (ui->cbRegisterType->currentText() == QString("輸入寄存器")){type = QModbusDataUnit::InputRegisters;}else if (ui->cbRegisterType->currentText() == QString("保持寄存器")){type = QModbusDataUnit::HoldingRegisters;}qDebug() << "請(qǐng)求報(bào)文類型: " << type;//獲取int startAddress = ui->sbWriteStartAddr->value();Q_ASSERT(startAddress >= 0 && startAddress < 10);quint16 numberOfEntries = ui->cbWriteCount->currentText().toUShort();//qDebug() << "Test: " << startAddress << " " << numberOfEntries;return QModbusDataUnit(type, startAddress, numberOfEntries); }//連接和斷開連接的槽函數(shù) void MainWindow::onConnectButtonClicked() {if (!modbusDevice){return;}//清空狀態(tài)欄消息statusBar()->clearMessage();if (modbusDevice->state() != QModbusDevice::ConnectedState){auto type = static_cast<ModbusConnection>(ui->cbConnType->currentIndex());if (type == Serial){//設(shè)置串口連接信息modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,m_settingDialog->settings().serialName);modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,m_settingDialog->settings().parity);modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,m_settingDialog->settings().baud);modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,m_settingDialog->settings().dataBits);modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,m_settingDialog->settings().stopBits);}else{//TCP連接信息const QUrl url = QUrl::fromUserInput(ui->lineEditPort->text());modbusDevice->setConnectionParameter(QModbusDevice::NetworkPortParameter,url.port());modbusDevice->setConnectionParameter(QModbusDevice::NetworkAddressParameter,url.host());}modbusDevice->setTimeout(m_settingDialog->settings().responseTime);modbusDevice->setNumberOfRetries(m_settingDialog->settings().numberOfRetries);if (!modbusDevice->connectDevice()){statusBar()->showMessage(tr("Connect failed..") + modbusDevice->errorString(), 5000);}else{statusBar()->showMessage(tr("Connect Successfully"), 5000);qDebug() << "連接OK";ui->actionConnect->setEnabled(false);ui->actionDisconnect->setEnabled(true);//使能讀寫操作ui->btnRead->setEnabled(true);ui->btnWrite->setEnabled(true);ui->btnReadWrite->setEnabled(true);}}else{//斷開連接modbusDevice->disconnectDevice();ui->actionConnect->setEnabled(true);ui->actionDisconnect->setDisabled(true);qDebug() << "斷開連接成功";//禁用讀寫操作ui->btnRead->setEnabled(false);ui->btnWrite->setEnabled(false);ui->btnReadWrite->setEnabled(false);} }//連接類型槽函數(shù) TCP Serial void MainWindow::onConnectTypeChanged(int index) {//如果之前存在連接,則斷開連接,然后釋放內(nèi)存if(modbusDevice){modbusDevice->disconnectDevice();delete modbusDevice;modbusDevice = nullptr;}auto type = static_cast<ModbusConnection>(index);if (type == Serial){modbusDevice = new QModbusRtuSerialMaster(this);qDebug() << "new QModbusRtuSerialMaster Ok";statusBar()->showMessage("new QModbusRtuSerialMaster Ok", 3000);}else if (type == Tcp){modbusDevice = new QModbusTcpClient(this);if (ui->lineEditPort->text().isEmpty())ui->lineEditPort->setText(QLatin1String("127.0.0.1:10086"));}else{statusBar()->showMessage("連接類型非法", 5000);}connect(modbusDevice, &QModbusClient::errorOccurred, [this](QModbusDevice::Error){statusBar()->showMessage(modbusDevice->errorString(), 5000);});if (!modbusDevice){//分配空間失敗ui->btnConnect->setDisabled(true);if (type == Serial){statusBar()->showMessage(tr("創(chuàng)建Modbus Master失敗"), 5000);}else{statusBar()->showMessage(tr("創(chuàng)建Modbus Client失敗"), 5000);}}else{connect(modbusDevice, &QModbusClient::stateChanged,this, &MainWindow::onModbusStateChanged);}}//Modbus狀態(tài)改變槽函數(shù) void MainWindow::onModbusStateChanged(int state) {//判斷Modbus設(shè)備連接是否處于連接狀態(tài)bool connected = (state != QModbusDevice::UnconnectedState);ui->actionConnect->setEnabled(!connected);ui->actionDisconnect->setEnabled(connected);if (QModbusDevice::UnconnectedState == state){ui->btnConnect->setText(tr("Connect"));}else{ui->btnConnect->setText(tr("Disconnect"));} }//讀操作槽函數(shù) void MainWindow::onReadButtonClicked() {if (!modbusDevice){return;}ui->textEditRead->clear();statusBar()->clearMessage();//發(fā)送請(qǐng)求報(bào)文數(shù)據(jù)auto *reply = modbusDevice->sendReadRequest(readRequest(), ui->sbServerAddr->value());if (reply){if (!reply->isFinished()){//完畢之后 自動(dòng)觸發(fā)槽函數(shù)connect(reply, &QModbusReply::finished, this, &MainWindow::onReadReady);}else{//廣播消息 不需要返回響應(yīng)delete reply;}}else{statusBar()->showMessage(tr("Read Error: ") + modbusDevice->errorString(), 5000);}}//讀取數(shù)據(jù) void MainWindow::onReadReady() {auto reply = qobject_cast<QModbusReply*>(sender());if (!reply){return;}if (reply->error() == QModbusDevice::NoError){const QModbusDataUnit data = reply->result();for (int i = 0, total = (int)data.valueCount(); i < total; i++){const QString str = tr("Address: %1 Value: %2").arg(data.startAddress() + i).arg(QString::number(data.value(i), data.registerType() <= QModbusDataUnit::Coils ? 10 : 16));ui->textEditRead->append(str);}}else if (reply->error() == QModbusDevice::ProtocolError){statusBar()->showMessage(tr("Read response error: %1 (Modbus exception: 0x%2)").arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), 5000);}else{statusBar()->showMessage(tr("Read response error: %1 (Code: 0x%2)").arg(reply->errorString()).arg(reply->error(), -1, 16), 5000);}//釋放內(nèi)存reply->deleteLater(); }void MainWindow::onWriteButtonClicked() {if (!modbusDevice){return;}statusBar()->clearMessage();QModbusDataUnit writeData = writeRequest();QModbusDataUnit::RegisterType type = writeData.registerType();//qDebug() << "test: " << writeData.valueCount();for (int i = 0, total = (int)(writeData.valueCount()); i < total; i++){if (type == QModbusDataUnit::Coils){writeData.setValue(i, writeModel->m_coils[i + writeData.startAddress()]);}else{//qDebug() << "test: " << writeModel->m_holdingRegisters[i + writeData.startAddress()];writeData.setValue(i, writeModel->m_holdingRegisters[i + writeData.startAddress()]);}}qDebug() << "寫數(shù)據(jù)內(nèi)容為:" << writeData.values();//發(fā)送請(qǐng)求報(bào)文數(shù)據(jù)auto *reply = modbusDevice->sendWriteRequest(writeData, ui->sbServerAddr->value());if (reply){if (!reply->isFinished()){//完畢之后 自動(dòng)觸發(fā)槽函數(shù)connect(reply, &QModbusReply::finished, this, [this, reply]{if (reply->error() == QModbusDevice::ProtocolError){statusBar()->showMessage(tr("Write Protocaol response error: %1").arg(reply->errorString()), 5000);}else if (reply->error() != QModbusDevice::NoError){statusBar()->showMessage(tr("Write response error: %1").arg(reply->errorString()), 5000);}else{qDebug() << "寫響應(yīng)的數(shù)據(jù): " << reply->result().values();}reply->deleteLater();});}else{//廣播消息 不需要返回響應(yīng)reply->deleteLater();}}else{statusBar()->showMessage(tr("Write Error: ") + modbusDevice->errorString(), 5000);} }//讀寫按鈕槽函數(shù) void MainWindow::onReadWriteButtonClicked() {if (!modbusDevice){return;}statusBar()->clearMessage();QModbusDataUnit writeData = writeRequest();QModbusDataUnit::RegisterType type = writeData.registerType();//qDebug() << "test: " << writeData.valueCount();for (int i = 0, total = (int)(writeData.valueCount()); i < total; i++){if (type == QModbusDataUnit::Coils){writeData.setValue(i, writeModel->m_coils[i + writeData.startAddress()]);}else{//qDebug() << "test: " << writeModel->m_holdingRegisters[i + writeData.startAddress()];writeData.setValue(i, writeModel->m_holdingRegisters[i + writeData.startAddress()]);}}qDebug() << "寫數(shù)據(jù)內(nèi)容為:" << writeData.values();//發(fā)送請(qǐng)求報(bào)文數(shù)據(jù)auto *reply = modbusDevice->sendReadWriteRequest(readRequest(), writeData, ui->sbServerAddr->value());if (reply){if (!reply->isFinished()){connect(reply, &QModbusReply::finished, this, &MainWindow::onReadReady);//完畢之后 自動(dòng)觸發(fā)槽函數(shù)connect(reply, &QModbusReply::finished, this, [this, reply]{if (reply->error() == QModbusDevice::ProtocolError){statusBar()->showMessage(tr("Write Protocaol response error: %1").arg(reply->errorString()), 5000);}else if (reply->error() != QModbusDevice::NoError){statusBar()->showMessage(tr("Write response error: %1").arg(reply->errorString()), 5000);}else{qDebug() << "寫響應(yīng)的數(shù)據(jù): " << reply->result().values();}reply->deleteLater();});}else{//廣播消息 不需要返回響應(yīng)reply->deleteLater();}}else{statusBar()->showMessage(tr("Write Error: ") + modbusDevice->errorString(), 5000);} }void MainWindow::onWriteTableChanged(int index) {const bool coilsOrHolding = index == 0 || index == 3;if (coilsOrHolding){ui->treeViewWrite->setColumnHidden(1, index != 0);ui->treeViewWrite->setColumnHidden(2, index != 3);ui->treeViewWrite->resizeColumnToContents(0);}ui->btnReadWrite->setEnabled(index == 3);ui->btnWrite->setEnabled(coilsOrHolding);ui->groupBox_2->setEnabled(coilsOrHolding); }

08. 程序下載

QModbus TCP模式客戶端讀操作(一).rar

QModbus TCP模式綜合操作(二).rar

09. 附錄

9.1 Qt教程匯總
網(wǎng)址:https://dengjin.blog.csdn.net/article/details/115174639

總結(jié)

以上是生活随笔為你收集整理的【Qt】modbus之TCP模式读操作的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。