【教程】从零开始用QT简易实现modbus通信
year599168784 2024-07-13 14:35:04 阅读 66
前言:本文旨在让读者了解在qt6中实现modbus通信主要使用哪些函数,需要引用哪些库和头文件,不对modbus协议进行介绍,仅在代码层面简单实现一个modbus通信案例
实现效果:点击读取按钮可以读取从机中的十个寄存器,点击写入按钮可以将从机0x02地址的寄存器写入数值3
开发环境:QT6
工程源码:链接:https://pan.baidu.com/s/1GFO7qe0GcjCUG9G_oojtsA?pwd=6b10
提取码:6b10
本文学习目标:实现由主机通过modbus RTU协议向从机发送读取/写入命令
第一步:下载相关软件:从机模拟软件ModbusSlave,虚拟串口配置器VSPD
链接:https://pan.baidu.com/s/1F4bHn1sO_dAvcn2xjq8Cjg?pwd=tudu
提取码:tudu
第二步:创建一个qt工程,这里起名modbus_example
创建工程的其他参数使用默认值即可
第三步:绘制ui
双击mainwindow.ui打开ui设计界面,添加4个push button和1个plain text edit,然后对QWidget点击栅格布局
把四个按钮的objectName依次改为btn_open,btn_close,btn_read,btn_write
第四步:添加库和头文件
1、在pro文件中添加serialport和serialbus库
2、在.h文件中添加相关的头文件
<code>#include <QSerialPort>
#include <QtSerialBus>
#include <QModbusDataUnit>
#include <QModbusClient>
第五步:添加数据成员
在mainwindow.h中添加private成员modbus Device;
第六步:编写【打开串口】按钮的槽函数
1、在ui界面右键【打开串口】按钮,选择转到槽,再选择clicked(),确认
2、在槽函数中设置串口的各项参数
<code>void MainWindow::on_btn_open_clicked()
{
// 设置modbus串口参数
modbusDevice.setConnectionParameter(QModbusDevice::SerialPortNameParameter, QStringLiteral("COM1")); //串口名:COM1
modbusDevice.setConnectionParameter(QModbusDevice::SerialBaudRateParameter, QSerialPort::Baud9600); //波特率:9600
modbusDevice.setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8); //数据位:8位
modbusDevice.setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop); //停止位:1位
modbusDevice.setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::NoParity); //校验位:无校验
3、在槽函数中添加以下代码,其中connectDevice()函数实现连接串口
//打开串口
if (!modbusDevice.connectDevice())
{
ui->plainTextEdit->insertPlainText("串口连接失败!");
return;
}
else
{
ui->plainTextEdit->insertPlainText("串口连接成功!");
}
4、编译运行工程文件,检查有无问题,点击打开串口后,文本框中应出现“串口连接成功”
第七步:添加【关闭串口】按钮的槽函数
1、添加按钮的槽函数,与第六步步骤相同
2、输入以下代码
<code>void MainWindow::on_btn_close_clicked()
{
modbusDevice.disconnectDevice();
ui->plainTextEdit->insertPlainText("串口已关闭!");
}
3、运行工程进行检查
第八步:编写【读取寄存器】按钮的槽函数
1、给按钮添加槽函数
2、输入以下代码
<code>void MainWindow::on_btn_read_clicked()
{
//定义"读请求"对象
QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters, 0, 10); //0是所要读取的寄存器起始地址,10是所要读取的寄存器个数
//发送请求
auto *reply = modbusDevice.sendReadRequest(readUnit, 1);
//连接信号与槽
connect(reply, &QModbusReply::finished, this,&MainWindow::onReadyRead);
}
在这里,我们还没有定义onReadyRead函数,所以会报错
3、声明与定义onReadyRead函数:
在Mainwindow.h的private slots一栏输入void onReadyRead(),声明onReadyRead函数,右键->重构->在mainwindow.cpp中添加定义
在onReadyRead()函数中添加代码
<code>void MainWindow::onReadyRead()
{
auto reply=qobject_cast<QModbusReply *>(sender()); //接收信号,并将信号发送者强制转换成QModbusReply类的对象
//检测回复是否正常
if (reply->error() == QModbusDevice::NoError) //从机回复无异常
{
ui->plainTextEdit->insertPlainText("读取成功!");
reply->deleteLater(); //稍后卸载reply
}
else //从机回复异常
{
ui->plainTextEdit->insertPlainText("读取失败!");
reply->deleteLater(); //稍后卸载reply
return;
}
// 从reply中获取数据单元
const QModbusDataUnit unit = reply->result();
// 将数据值转换为字符串
QString dataStr;
for (int i = 0; i < unit.valueCount(); ++i) {
dataStr += QString::number(unit.value(i)) + " ";
}
// 输出到plainTextEdit控件中
ui->plainTextEdit->insertPlainText("数据值:" + dataStr);
}
4、运行文件检验
先打开VSPD虚拟串口配置器,点击Add Pair
打开modbusSlave,双击改变寄存器中的值
点击上方工具栏中的Connection,按照图中参数设置,然后点击OK
回到QT,编译运行工程项目,先点击【打开串口】,再点击【读取寄存器】,成功读取从0x00地址开始的10个寄存器中的值
看到以上内容即为成功
第九步:添加【写入寄存器】的槽函数
1、给按钮添加槽函数
2、输入代码
<code>void MainWindow::on_btn_write_clicked()
{
// 检查modbusDevice的连接状态
if (modbusDevice.state() != QModbusDevice::ConnectedState) {
ui->plainTextEdit->insertPlainText("写入失败!");
return;
}
// 创建QModbusDataUnit对象,用于写入寄存器
QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters, 0x02, 1); // 写入寄存器起始地址0x02,写入寄存器数量1
// 设置要写入的数据值为0
writeUnit.setValue(0, 3); //参数1:寄存器索引的偏移量,参数2:写入的值
// 发送写入请求
modbusDevice.sendWriteRequest(writeUnit, 1); //写入请求,写入从机ID
ui->plainTextEdit->insertPlainText("写入成功");
}
3、运行检查
点击写入寄存器后,观察到从机中地址为0x02的寄存器值被修改为了3,写入成功
结语:
本文仅展示了实现modbus通信实现读取和写入功能有哪些需要使用的函数、库、头文件,为了使代码简洁,没有实现对通信异常情况的处理,读者学习后可以自行修改相关参数,或自行定义函数提供用户交互界面去变更这些参数,实现更加复杂的功能
上一篇: 【C++】string学习 — 手搓string类项目
下一篇: 有效 java.sql.SQLNonTransientConnectionException:Could not create connection to database server异常的正确解决
本文标签
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。