一、一些概念
1.Modbus由施耐德旗下Modicon在1979年推出,工业现场最通用、免费开放的应用层问答式通信协议。
2.Modbus协议采用主从架构(CS架构)。通信过程中,由主站(客户端)发送指令包,从站(服务端)响应回报,构成一次完整的通信过程;
3.底层物理实现链路:
1)Modbus-RTU: 运行在RS485/RS232串口;
2)Modbus-TCP: 运行在以太网 TCP,默认端口 502;
3)Modbus-ASCII: 串口明文十六进制字符传输。
4.三者上层PDU(协议数据单元,功能码 + 数据部分)完全相同,仅底层帧封装、校验、链路规则不同而已;
5.四类存储寄存器
Modbus把所有设备数据划分成4类独立地址空间:
1)线圈Coils,可读、可写,数据位宽1bit;
2)离散输入Discrete Inputs,只读,数据位宽1bit;
3)输入寄存器Input Registers,只读,数据位宽16bit无符号整型;
4)保持寄存器Holding Registers,可读、可写,数据位宽16bit无符号整型。
二、 Modbus-RTU报文帧结构(串口二进制)
从站地址(1字节)] + PDU协议数据单元 + CRC16校验(2字节)。
三、测试
整个测试流程:Qt程序是主站、SSCOM软件为从站。主站向从站发送Modbus协议帧报文,从站收到后分析。
1.例如 发送报文格式(查询命令) 01 03 00 00 00 02 C4 0B
第1字节01: 从站 ID = 1;
第2字节03: 功能码,读取保持寄存器;
第3、4字节00 00: 起始寄存器地址0;
第5、6字节00 02: 读取寄存器数量2个寄存器;
第7字节C4: CRC校验低字节;
第8字节0B: CRC校验高字节;
2.源码
main.cpp
cpp
#include <QCoreApplication>
#include <QDebug>
#include <QtSerialBus/QModbusRtuSerialMaster>
#include <QtSerialBus/QModbusReply>
#include <QtSerialPort/QSerialPort>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QModbusRtuSerialMaster master;
// 绑定虚拟串口COM1
#if 1
master.setConnectionParameter(QModbusDevice::SerialPortNameParameter, "COM1");
master.setConnectionParameter(QModbusDevice::SerialBaudRateParameter, QSerialPort::Baud115200);
master.setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8);
master.setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop);
master.setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::NoParity);
if (!master.connectDevice())
{
qDebug()<<"串口打开失败:"<<master.errorString();
return -1;
}
qDebug()<<"RTU主站启动成功,准备发送报文";
// 1.定义读取单元:保持寄存器、起始地址0、读取2个
QModbusDataUnit readItem(QModbusDataUnit::HoldingRegisters, 0, 2);
// 2.发送请求,从站ID = 1
QModbusReply *reply = master.sendReadRequest(readItem, 1);
// 3.必须先判空,再绑定finished信号,杜绝空指针connect报错
if (reply)
{
QObject::connect(reply, &QModbusReply::finished, [reply]()
{
// 读取应答数据
if(!reply->isFinished())
return;
const QModbusDataUnit res = reply->result();
qDebug() << "读到寄存器数值:" << res.values();
reply->deleteLater();
});
}
else
{
qDebug() << "请求发送失败:" << master.errorString();
}
#endif
return a.exec();
}

3.程序运行结果

4.仿真环境搭建请参考<Qt实现串口通信及使用VSPD模拟调试>
四、开发工具及Qt版本
开发工具:Qt Creator 4.10.2
Qt版本:Qt_5_12_6