Qt ModbusTCP和ModBusRTU读写数据

embedded/2025/2/23 23:44:50/

文章目录

  • ModbusTCP和ModBusRTU 的区别
  • ModbusTCP
    • 添加模块
    • ModBus读写
  • ModBusRTU
    • 添加模块

ModbusTCP和ModBusRTU 的区别

Modbus RTU 和 Modbus TCP 是 Modbus 协议的两种不同实现方式,主要区别如下:

  1. 通信介质

    Modbus RTU:基于串行通信(如 RS-232 或 RS-485),使用二进制编码传输数据。

    Modbus TCP:基于以太网,使用 TCP/IP 协议,数据通过以太网传输。

  2. 数据编码

    Modbus RTU:采用二进制编码,数据紧凑,传输效率高。

    Modbus TCP:数据封装在 TCP/IP 数据包中,增加了 IP 地址和端口号等信息。

  3. 传输速度

    Modbus RTU:速度受限于串行通信,通常较慢。

    Modbus TCP:基于以太网,速度更快,适合高速数据传输。

  4. 传输距离

    Modbus RTU:RS-485 最大传输距离约 1200 米。

    Modbus TCP:理论上无距离限制,实际受网络设备影响。

  5. 网络拓扑

    Modbus RTU:通常为总线型拓扑,设备串联。

    Modbus TCP:支持星型、树型等多种拓扑,设备通过交换机或路由器连接。

  6. 协议开销

    Modbus RTU:协议开销小,数据帧简单。

    Modbus TCP:协议开销较大,增加了 TCP/IP 包头。

  7. 应用场景

    Modbus RTU:适用于工业控制、传感器网络等低速、短距离场景。

    Modbus TCP:适用于需要高速、远距离通信的工业自动化系统。

  8. 设备成本

    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); // 设置UIQWidget::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()<<"连接成功";elseqDebug()<<"连接失败";
}// 当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(); // 如果请求失败,输出错误信息}
}

http://www.ppmy.cn/embedded/164703.html

相关文章

Linux基本指令(三)+ 权限

文章目录 基本指令grep打包和压缩zip/unzipLinux和windows压缩包互传tar&#xff08;重要&#xff09;Linux和Linux压缩包互传 bcuname -r常用的热键关机外壳程序 知识点打包和压缩 Linux中的权限用户权限 基本指令 grep 1. grep可以过滤文本行 done用于标记循环的结束&#x…

MySQL 一条 SQL 执行流程解析

MySQL 的 SQL 执行过程其实是一个非常复杂的多阶段流程。每当我们在客户端发出一条 SQL 语句时&#xff0c;MySQL 会经过多个步骤来处理并执行它。在这里&#xff0c;我们将详细地介绍 MySQL 执行 SQL 语句的完整流程&#xff0c;从 SQL 语句的解析到结果的返回。 1. 客户端请…

初级渗透测试工程师需要学什么?网络安全零基础入门到精通教程建议收藏!

1、前言 本文主要介绍如何成为一名初级的渗透测试工程师所需要学习的内容&#xff0c;后续也会基于此将自己的学习总结、心得记录下来。相信在不断坚持下&#xff0c;争取在今年五月初成为一名初级的渗透测试工程师。 2、涉及知识领域 基础网络知识&#xff1a; 理解TCP/IP协…

深入解析:在Spring Boot中集成MyBatis Plus实现高效数据库操作

前后端微服务商城项目&#xff0c;手把手教学&#xff01; 在Spring Boot中集成第三方框架&#xff0c;实际上是非常常见的一种做法。Spring Boot自带了很多开箱即用的功能&#xff0c;但在实际项目开发中&#xff0c;我们经常需要借助一些第三方框架来实现更为复杂的功能。比如…

PHP约课健身管理系统小程序源码

&#x1f3cb;️‍♂️ 约课健身管理系统小程序&#xff1a;重塑健身预约体验&#xff0c;引领数字化健身新时代 一款基于ThinkPHPUniapp框架&#xff0c;由米扬精心雕琢的约课健身管理系统小程序&#xff0c;专为健身房、健身工作室、运动会所、运动场馆、瑜伽馆、拳馆等泛健…

Git常见命令--助力开发

git常见命令&#xff1a; 创建初始化仓库&#xff1a; git 将文件提交到暂存区 git add 文件名 将文件提交到工作区 git commit -m "注释&#xff08;例如这是发行的版本1&#xff09;" 文件名 查看状态 如果暂存区没有文件被提交显示&#xff1a; $ git status On…

14.7 LangChain Experimental 模块解析:解锁 Auto-GPT 开发新范式

LangChain Experimental 模块解析:解锁 Auto-GPT 开发新范式 关键词:LangChain Experimental、Auto-GPT 实现、自主智能体开发、Agent 架构设计、实验性功能实践 1. LangChain Experimental 模块的定位与核心能力 模块定位解析: #mermaid-svg-4xz2OlZBUFjkBmqw {font-fami…

MySQL 单表访问方法详解

单表访问 MySQL 单表访问方法详解&#xff1a;高效查询之道**一、 查询执行基础****二、 访问方法 (Access Method) 概念****三、 具体访问方法 (从最优到最差)****四、 注意事项****五、 总结与优化建议****六、 电商网站数据存储应用示例****七、 数据备份与恢复模型 (补充)*…