QtModbusTCP和ModBusRTU读写数据
- IT业界
- 2025-08-28 20:39:02

文章目录 ModbusTCP和ModBusRTU 的区别ModbusTCP添加模块ModBus读写 ModBusRTU添加模块 ModbusTCP和ModBusRTU 的区别
Modbus RTU 和 Modbus TCP 是 Modbus 协议的两种不同实现方式,主要区别如下:
通信介质
Modbus RTU:基于串行通信(如 RS-232 或 RS-485),使用二进制编码传输数据。
Modbus TCP:基于以太网,使用 TCP/IP 协议,数据通过以太网传输。
数据编码
Modbus RTU:采用二进制编码,数据紧凑,传输效率高。
Modbus TCP:数据封装在 TCP/IP 数据包中,增加了 IP 地址和端口号等信息。
传输速度
Modbus RTU:速度受限于串行通信,通常较慢。
Modbus TCP:基于以太网,速度更快,适合高速数据传输。
传输距离
Modbus RTU:RS-485 最大传输距离约 1200 米。
Modbus TCP:理论上无距离限制,实际受网络设备影响。
网络拓扑
Modbus RTU:通常为总线型拓扑,设备串联。
Modbus TCP:支持星型、树型等多种拓扑,设备通过交换机或路由器连接。
协议开销
Modbus RTU:协议开销小,数据帧简单。
Modbus TCP:协议开销较大,增加了 TCP/IP 包头。
应用场景
Modbus RTU:适用于工业控制、传感器网络等低速、短距离场景。
Modbus TCP:适用于需要高速、远距离通信的工业自动化系统。
设备成本
Modbus RTU:设备成本较低,适合预算有限的项目。
Modbus TCP:设备成本较高,但性能更强。
ModbusTCP 添加模块 ModBus读写 #ifndef WIDGET_H // 如果没有定义 WIDGET_H #define WIDGET_H // 定义 WIDGET_H,防止重复包含 #include <QWidget> // 包含QWidget类的定义,QWidget是所有UI对象的基础类 #include <QModbusTcpClient> // 包含QModbusTcpClient类的定义,用于实现Modbus TCP协议的客户端 QT_BEGIN_NAMESPACE // 开始Qt命名空间 namespace Ui { class Widget; } // 声明一个名为Widget的类在Ui命名空间中,通常由Qt Designer生成的UI类 QT_END_NAMESPACE // 结束Qt命名空间 class Widget : public QWidget // 定义Widget类,继承自QWidget { Q_OBJECT // 必须的宏,用于启用信号和槽机制 public: Widget(QWidget *parent = nullptr); // 构造函数,允许创建无父级窗口部件的对象,默认为nullptr ~Widget(); // 析构函数 QModbusTcpClient *modbusClient; // 指向QModbusTcpClient类型的指针,用于管理与Modbus TCP服务器的连接 private slots: // 私有槽,用于处理特定事件或响应信号 void on_ReadBtn_clicked(); // 当ReadBtn按钮被点击时调用的槽函数 void ReceiveData(); // 接收数据的槽函数 void on_WriteBtn_clicked(); // 当WriteBtn按钮被点击时调用的槽函数 private: // 私有成员变量和函数 Ui::Widget *ui; // 指向Ui::Widget实例的指针,该实例包含了通过Qt Designer设计的UI元素 bool isconnect; // 标志位,表示是否已经连接到Modbus TCP服务器 void ReadValue(); // 读取值的私有函数 }; #endif // WIDGET_H // 结束WIDGET_H的条件编译指令 #include "widget.h" #include "ui_widget.h" #include <QModbusTcpClient> #include <QModbusDataUnit> #include <QModbusReply> #include <QMessageBox> #include <QDebug> Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); modbusClient = new QModbusTcpClient(this); modbusClient->setConnectionParameter(QModbusDevice::NetworkPortParameter, 503); // 设置Modbus端口 modbusClient->setConnectionParameter(QModbusDevice::NetworkAddressParameter, "127.0.0.1"); // 设置Modbus服务器地址 if (!modbusClient->connectDevice()) { qDebug() << "连接失败"; } } Widget::~Widget() { if(modbusClient->state() == QModbusTcpClient::ConnectedState) { modbusClient->disconnectDevice(); } delete ui; } //写入数据 void Widget::on_WriteBtn_clicked() { if(ui->tb_Line->text() == "") { QMessageBox::warning(this,"提示","请输入设定值!"); return; } if(modbusClient->state() == QModbusDevice::ConnectedState) { QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters, 0, 1); // 写入一个寄存器 writeUnit.setValue(0,ui->tb_Line->text().toUInt()); if (auto *reply = modbusClient->sendWriteRequest(writeUnit, 1)) { reply->deleteLater(); } } } //读取数据 void Widget::on_ReadBtn_clicked() { ReadValue(); } //读取Modbus数据 void Widget::ReadValue() { if(modbusClient->state() == QModbusDevice::ConnectedState) { QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters, 0, 1); // 读取一个寄存器 if (auto *reply = modbusClient->sendReadRequest(readUnit, 1)) { if (!reply->isFinished()) { connect(reply,QModbusReply::finished,this,ReceiveData); return; } reply->deleteLater(); } else { qDebug()<< "提前退出"; } } } void Widget::ReceiveData() { QModbusReply* reply = (QModbusReply*)(sender()); QModbusDataUnit unit = reply->result(); reply->deleteLater(); if(unit.valueCount() > 0) { ui->lb_templbtemp->setText(QString::number(unit.value(0))); } } ModBusRTU 添加模块 #ifndef WIDGET_H // 如果没有定义WIDGET_H #define WIDGET_H // 定义WIDGET_H,防止重复包含 #include <QWidget> // 包含QWidget类,所有用户界面对象的基础类 #include <QModbusRtuSerialMaster> // 包含QModbusRtuSerialMaster类,用于实现Modbus RTU协议主站功能 #include <QModbusDataUnit> // 包含QModbusDataUnit类,用于表示Modbus数据单元 namespace Ui { // 定义命名空间Ui class Widget; // 声明一个名为Widget的类,在此命名空间中,通常由Qt Designer生成的UI类 } class Widget : public QWidget // 定义Widget类,继承自QWidget { Q_OBJECT // 必须的宏,用于启用信号和槽机制 public: explicit Widget(QWidget *parent = 0); // 构造函数,explicit防止隐式转换,默认父级窗口部件为nullptr ~Widget(); // 析构函数 QModbusRtuSerialMaster *modbusMaster; // 指向QModbusRtuSerialMaster类型的指针,用于管理与Modbus RTU从站设备的通信 private slots: // 私有槽,处理特定事件或响应信号 void on_pushButton_clicked(); // 当pushButton按钮被点击时调用的槽函数 void on_pushButton_2_clicked(); // 当pushButton_2按钮被点击时调用的槽函数 private: Ui::Widget *ui; // 指向Ui::Widget实例的指针,该实例包含了通过Qt Designer设计的UI元素 void IniModbus(); // 初始化Modbus主站配置的私有成员函数 }; #endif // WIDGET_H // 结束WIDGET_H的条件编译指令 #include "widget.h" #include "ui_widget.h" #include "QDebug" #include <QSerialPort> // Widget类构造函数,初始化成员变量和UI组件 Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); // 设置UI QWidget::setWindowTitle("ModbusRTU Demo"); // 设置窗口标题 IniModbus(); // 初始化Modbus主站配置 } // Widget类析构函数,释放资源 Widget::~Widget() { delete ui; // 删除UI对象 } // 初始化Modbus RTU主站配置 void Widget::IniModbus() { modbusMaster = new QModbusRtuSerialMaster(this); // 创建一个新的QModbusRtuSerialMaster实例 // 设置连接参数 modbusMaster->setConnectionParameter(QModbusDevice::SerialPortNameParameter, "COM1"); modbusMaster->setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::EvenParity); modbusMaster->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, QSerialPort::Baud9600); modbusMaster->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8); modbusMaster->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop); // 尝试连接设备 if(modbusMaster->connectDevice()) qDebug()<<"连接成功"; else qDebug()<<"连接失败"; } // 当pushButton按钮被点击时调用此槽函数 void Widget::on_pushButton_clicked() { // 创建读取单元 QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters, 0, 1); if (auto *reply = modbusMaster->sendReadRequest(readUnit, 1)) { // 发送读请求 // 等待回复完成 while (!reply->isFinished()) { QCoreApplication::processEvents(); // 处理事件循环 } // 检查错误 if (reply->error() == QModbusDevice::NoError) { const QModbusDataUnit resultUnit = reply->result(); QString result = ""; for (int i = 0; i < resultUnit.valueCount(); ++i) { result += QString::number(resultUnit.value(i)) + " "; // 构造结果字符串 } ui->label->setText(result); // 显示结果 } else { qDebug()<<reply->errorString(); // 输出错误信息 } reply->deleteLater(); // 安全删除回复对象 } else { qDebug()<<modbusMaster->errorString(); // 如果请求失败,输出错误信息 } } // 当pushButton_2按钮被点击时调用此槽函数 void Widget::on_pushButton_2_clicked() { // 创建写入单元 QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters, 0, 1); qint32 value = ui->lineEdit->text().toInt(); // 获取输入框中的值 writeUnit.setValue(0, value); // 设置写入值 if (auto *reply = modbusMaster->sendWriteRequest(writeUnit, 1)) { // 发送写请求 // 等待回复完成 while (!reply->isFinished()) { QCoreApplication::processEvents(); // 处理事件循环 } // 检查错误 if (reply->error() == QModbusDevice::NoError) { qDebug()<< "写入成功"; // 输出成功信息 } else { qDebug()<< "写入失败" + reply->errorString(); // 输出错误信息 } reply->deleteLater(); // 安全删除回复对象 } else { qDebug()<< "写入失败" + modbusMaster->errorString(); // 如果请求失败,输出错误信息 } }QtModbusTCP和ModBusRTU读写数据由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“QtModbusTCP和ModBusRTU读写数据”
下一篇
React之旅-02创建项目