【教程】从零开始用QT简易实现modbus通信

前言:本文旨在让读者了解在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文件中添加相关的头文件

#include <QSerialPort>
#include <QtSerialBus>
#include <QModbusDataUnit>
#include <QModbusClient>

第五步:添加数据成员

在mainwindow.h中添加private成员modbus Device;

第六步:编写【打开串口】按钮的槽函数

1、在ui界面右键【打开串口】按钮,选择转到槽,再选择clicked(),确认

2、在槽函数中设置串口的各项参数

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、输入以下代码

void MainWindow::on_btn_close_clicked()
{
    modbusDevice.disconnectDevice();
    ui->plainTextEdit->insertPlainText("串口已关闭!");
}

3、运行工程进行检查

第八步:编写【读取寄存器】按钮的槽函数

1、给按钮添加槽函数

2、输入以下代码

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()函数中添加代码

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、输入代码

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通信实现读取和写入功能有哪些需要使用的函数、库、头文件,为了使代码简洁,没有实现对通信异常情况的处理,读者学习后可以自行修改相关参数,或自行定义函数提供用户交互界面去变更这些参数,实现更加复杂的功能

Qt是一个跨平台的C++开发框架,提供了丰富的功能和工具,可以实现各种类型的应用程序开发。要在Qt实现Modbus从机功能,可以使用Qt的串口通信库和Modbus协议库进行开发。 首先,我们需要使用Qt的串口通信库来建立连接并配置串口。可以通过使用QSerialPort类来访问和控制串口。使用类似下面的代码来创建一个QSerialPort对象,并设置串口的参数: ``` QSerialPort serialPort; serialPort.setPortName("COM1"); // 设置串口名字 serialPort.setBaudRate(QSerialPort::Baud9600); // 设置波特率 serialPort.setDataBits(QSerialPort::Data8); // 设置数据位 serialPort.setParity(QSerialPort::NoParity); // 设置校验位 serialPort.setStopBits(QSerialPort::OneStop); // 设置停止位 ``` 之后,我们需要使用QtModbus协议库来实现Modbus从机功能。可以使用QModbusServer类来创建一个Modbus从机对象,并配置从机的地址和功能码: ``` QModbusServer modbusServer; modbusServer.setConnectionParameter(QModbusServer::SerialPortNameParameter, "COM1"); // 设置Modbus从机连接的串口 modbusServer.setServerAddress(1); // 设置Modbus从机地址 // 设置Modbus从机支持的功能码 modbusServer.setData(MODBUS_SERVER_READ_HOLDING_REGISTERS, new ModbusServerData()); modbusServer.setData(MODBUS_SERVER_WRITE_SINGLE_REGISTER, new ModbusServerData()); ``` 接下来,我们可以使用Qt的信号槽机制来处理串口数据的接收和发送,并实现Modbus从机的功能。可以通过使用QSerialPort的readyRead()信号来接收串口数据,并解析Modbus请求。根据不同的功能码,执行相应的操作,并根据需要发送Modbus响应。 总结起来,通过使用Qt的串口通信库和Modbus协议库,我们可以很方便地在Qt实现Modbus从机功能。需要建立串口连接并配置参数,创建Modbus从机对象并设置地址和功能码,使用信号槽机制处理串口数据的接收和发送,实现Modbus从机的功能。上述代码仅作为示例,具体实现根据需要进行调整和扩展。
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值