Modbus RTU协议

简介

Modbus RTU(Remote Terminal Unit)是Modbus通信协议的一种变体,用于串行通信。它定义了在串行通信中传输Modbus消息的规则和格式。

Modbus RTU协议采用二进制形式传输数据,使用RS-232或RS-485等串行通信接口。

关键特征:

帧格式:Modbus RTU帧由起始位、设备地址、功能码、数据、CRC校验和结束位组成。

起始位:用于标识一个字节的开始,让接收端知道数据传输的时序和起始位置。在Modbus RTU协议中,起始位也是一个字节的第一个位,用于标识一个Modbus消息的开始。在Modbus RTU中,起始位的持续时间为3.5个字符时间,即在传输速率为9600 bps的情况下,起始位持续时间为约364us。

设备地址:每个Modbus RTU设备都有一个唯一的设备地址,用于标识通信的目标设备。

功能码:功能码指示了Modbus操作的类型,如读取寄存器、写入寄存器等。

数据:数据部分包含要读取或写入的寄存器地址和相关数据。

CRC校验和:用于检测数据的完整性和准确性,防止数据传输错误。

帧间隔:Modbus RTU中,每个字节之间没有固定的时间间隔,而是通过静默时间来区分帧。

常用类

QModbusRtuSerialMaster:这个类是Modbus RTU通信的主站(Master)的实现类。它继承自QModbusClient类,并通过串口与Modbus从站(Slave)进行通信。

QModbusRtuSerialSlave:这个类是Modbus RTU通信的从站(Slave)的实现类。它继承自QModbusServer类,并通过串口接收和处理来自主站的通信请求。

QModbusDataUnit:这个类用于定义Modbus数据单元,包括功能码、起始地址、数据长度等信息。可以用于读取或写入Modbus设备的寄存器和线圈。

QModbusReply:这个类表示一个Modbus请求的响应。通过该类可以获取响应的结果、错误信息等。

QModbusRtuSerialMaster常用函数

setConnectionParameter:用于设置Modbus设备的连接参数。它接受两个参数:参数类型和参数值。

  • QModbusDevice::SerialPortNameParameter:串口名称,例如"/dev/ttyUSB0"。
  • QModbusDevice::SerialParityParameter:串口奇偶校验位,例如QSerialPort::NoParity表示无校验。
  • QModbusDevice::SerialBaudRateParameter:串口波特率,例如QSerialPort::Baud9600表示9600波特率。
  • QModbusDevice::SerialDataBitsParameter:串口数据位数,例如QSerialPort::Data8表示8位数据位。
  • QModbusDevice::SerialStopBitsParameter:串口停止位数,例如QSerialPort::OneStop表示1位停止位。

connectDevice:建立Modbus RTU串口连接。
disconnectDevice:断开Modbus RTU串口连接。

sendReadRequest:发送读取请求,读取指定地址的寄存器。该函数有多个重载版本,可以读取不同类型的寄存器,如输入寄存器、保持寄存器等。

sendWriteRequest:发送写入请求,向指定地址的寄存器写入数据。该函数有多个重载版本,可以写入不同类型的寄存器,如输入寄存器、保持寄存器等。

sendReadWriteRequest:发送读写请求,先读取指定地址的寄存器,再向其写入数据。

sendCustomRequest:发送自定义请求,可以用来发送一些特殊的Modbus请求,如读取设备标识符等。

state:获取当前连接状态,返回值为QModbusDevice::State枚举类型,表示设备的连接状态。

errorString:获取最后一次操作的错误信息。
dataCount:获取最后一次读取或写入的数据数量。
data:获取最后一次读取的数据,返回QModbusDataUnit类型,包含了读取到的数据。
setData:设置写入的数据。该函数只在发送写入请求前有效。

Modbus RTU服务端:

#include <QCoreApplication>
#include <QModbusRtuSerialServer>
#include <QSerialPort>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 创建串口对象
    QSerialPort serialPort;
    serialPort.setPortName("COM1"); // 设置串口号
    serialPort.setBaudRate(QSerialPort::Baud9600); // 设置波特率
    serialPort.setDataBits(QSerialPort::Data8); // 设置数据位
    serialPort.setParity(QSerialPort::NoParity); // 设置校验位
    serialPort.setStopBits(QSerialPort::OneStop); // 设置停止位

    // 打开串口
    if (!serialPort.open(QIODevice::ReadWrite)) {
        qDebug() << "Failed to open serial port:" << serialPort.errorString();
        return 1;
    }

    // 创建Modbus RTU服务端对象
    QModbusRtuSerialServer modbusServer;
    modbusServer.setConnectionParameter(QModbusDevice::SerialPortNameParameter, "COM1"); // 设置串口号
    modbusServer.setConnectionParameter(QModbusDevice::SerialBaudRateParameter, QSerialPort::Baud9600); // 设置波特率
    modbusServer.setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8); // 设置数据位
    modbusServer.setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::NoParity); // 设置校验位
    modbusServer.setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop); // 设置停止位

  // 连接dataWritten()信号,表示主站写入数据
  QObject::connect(&modbusServer, &QModbusRtuSerialServer::dataWritten, [&](int serverAddress, const QByteArray &data) {
        qDebug() << "Data written by master:" << data.toHex();
        // 在这里处理主站写入数据的逻辑
    });

  // 连接dataRead()信号,表示主站读取数据
  QObject::connect(&modbusServer, &QModbusRtuSerialServer::dataRead, [&](int serverAddress, const QByteArray &data) {
        qDebug() << "Data read by master:" << data.toHex();
        // 在这里处理主站读取数据的逻辑
    });
	
   // 启动服务端
   if (!modbusServer.connectDevice()) {
        qDebug() << "Failed to start Modbus server:" << modbusServer.errorString();
        return 1;
    }

  qDebug() << "Modbus server started";

    return a.exec();
}

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值