环境:Qt5.15.2

测试工具

  1. Virtual Serial Port Driver:用于创建成对的虚拟串口,一个用于发送,一个用于接收。
  2. Modbus Slave:用于模拟从机

示例

前提:打开Virtual Serial Port Driver,创建一对虚拟串口。Qt中实现Modbus简单通信的程序作为主机,Modbus Slava用于模拟从机。

  1. CMAKE核心配置:
# 设置源文件编码为UTF-8
if(MSVC)
    add_compile_options(/utf-8)

endif()

# 查找Qt5及其组件
find_package(QT NAMES Qt5 REQUIRED COMPONENTS Widgets SerialPort SerialBus)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets SerialPort SerialBus)

target_link_libraries(test_modbus PRIVATE Qt${QT_VERSION_MAJOR}::Widgets
    Qt${QT_VERSION_MAJOR}::SerialPort
    Qt${QT_VERSION_MAJOR}::SerialBus)
  1. 需要使用Modbus通信的类中组合QModbusRtuSerialMaster类对象:
#include <QModbusRtuSerialMaster>
QModbusRtuSerialMaster modbusDevice;
  1. 配置串口参数,打开串口

// 设置modbus串口参数
modbusDevice.setConnectionParameter(QModbusDevice::SerialPortNameParameter, QStringLiteral("COM4"));    //串口名: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);       //校验位:无校验

modbusDevice.connectDevice()

  1. 接收数据:
 //定义"读请求"对象
QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters, 0, 10);    //0是所要读取的寄存器起始地址,10是所要读取的寄存器个数
//向位于地址1的从机服务器发送请求
auto *reply = modbusDevice.sendReadRequest(readUnit, 1);
if (reply) {
    //读取完毕就执行onReadyRead
    connect(reply, &QModbusReply::finished, this,&MainWindow::onReadyRead);

}


// onReadyRead槽函数中
auto reply=qobject_cast<QModbusReply *>(sender());  //接收信号,并将信号发送者强制转换成QModbusReply类的对象

// 读取成功
if (reply->error() == QModbusDevice::NoError)       //从机回复无异常
{

    // 从reply中获取数据单元
    const QModbusDataUnit unit = reply->result();
    
    // 将数据值转换为字符串
    QString dataStr;
    for (int i = 0; i < unit.valueCount(); ++i) {
        dataStr += QString::number(unit.value(i)) + " ";
    }

    reply->deleteLater();                           //稍后卸载reply
}
// 读取失败
else                                                //从机回复异常
{
    reply->deleteLater();   //稍后卸载reply
    return;
}


  1. 发送数据:
// 检查modbusDevice的连接状态
if (modbusDevice.state() != QModbusDevice::ConnectedState) {
    return;
}

// 创建QModbusDataUnit对象,用于写入寄存器
QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters, 0x02, 1); // 写入寄存器起始地址0x02,写入寄存器数量1

// 设置要写入的数据值为0
writeUnit.setValue(0, 3); //参数1:寄存器索引的偏移量,参数2:写入的值

// 发送写入请求
modbusDevice.sendWriteRequest(writeUnit, 1);  //写入请求,写入地址为1的从机
ui->plainTextEdit->insertPlainText("写入成功");

  1. 关闭串口:
modbusDevice.disconnectDevice();