Qt C++实战:Modbus RTU协议详解及主站实现
文章目录
Modbus 总线协议属于应用层协议,是一种常见的工业系统通讯协议,被广泛应用于工业领域。本篇将对 Modbus RTU 协议进行详细介绍,并实现一个基于Qt的 Modbus RTU 主站上位机。
一 Modbus RTU 协议
1.1 Modbus 协议分类及通信过程
Modbus 协议分为三类,包括:Modbus-RTU,Modbus-ASCII和Modbus-TCP。
Modbus 是主从方式通信,通信由主机发起,一问一答式,从机无法主动向主机发送数据。
《GB/T 19582.2》中规定:RTU 模式中每个字节为11位,格式为:8bit数据位(先发地位)、1bit起始位、1bit奇偶校验、1bit停止位。默认使用偶校验,也可以使用其他模式(奇校验、无校验)。使用无校验时要求2个停止位,以此来满足11bit的数据。
发送字符或字节的顺序为从左到右,如下图所示:
通过配置,设备可以接受奇校验,偶校验或无校验,如果无校验,那么传送一个附加的停止位来填充字符帧使其成为完整的11位异步字符,如下图所示:
1.2 Modbus-RTU 协议数据帧格式
Modbus-RTU 帧最大长度为256字节,帧描述如下:
- 地址码:1个字节的从机地址码。0:广播地址;1-247:从机地址;248-255:保留;
- 功能码:常用的就是01、02、03、04、05、06、15和16,具体描述见下表;
- 数据区:数据区包括起始地址、数量和数据,这三项均是大端模式;
- CRC校验:两个字节,小端模式,校验的数据范围为:地址码+功能码+数据区。
功能码的具体描述见下表:
| 功能码 | 名称 | 作用 |
|---|---|---|
| 01 | 读取线圈状态 | 取得一组逻辑线圈的当前状态(ON/OFF) |
| 02 | 读取输入状态 | 取得一组开关输入的当前状态(ON/OFF) |
| 03 | 读取保持寄存器 | 在一个或多个保持寄存器中取得当前的二进制值 |
| 04 | 读取输入寄存器 | 在一个或多个输入寄存器中取得当前的二进制值 |
| 05 | 强置单线圈 | 强置一个逻辑线圈的通断状态 |
| 06 | 预置单寄存器 | 把具体二进制装入一个保持寄存器 |
| 07 | 读取异常状态 | 取得8个内部线圈的通断状态,这8个线圈的地址由控制器决定,用户逻辑可以将这些线圈定义,以说明从机状态,短报文适宜于迅速读取状态 |
| 08 | 会送诊断校验 | 把诊断校验报文送从机,以对通信处理进行评鉴 |
| 09 | 编程(只用于484) | 使主机模拟编程器作用,修改PC从机逻辑 |
| 10 | 控询(只用于484) | 可使主机与一台正在执行长程序任务从机通信,探询该从机是否完成其操作任务,仅在含有功能码9的报文发送后,本功能码才能发送 |
| 11 | 读取事件计数 | 可使主机发出单询问,并随即判定操作是否成功,尤其是该命令或其他应答产生通信错误时。 |
| 12 | 读取通信事件记录 | 可使主机检索每台从机的Modbus事务处理通信事件记录。如果某项事务处理完成,记录会给出相关错误 |
| 13 | 编程(184/384 484 584) | 可使主机模拟编程器功能修改PC从机逻辑 |
| 14 | 探询(184/384 484 584) | 可使主机与正在执行任务的从机通信,定期控询该从机是否已完成其程序操作,仅在含有功能13的报文发送后,本功能码才得发送 |
| 15 | 强置多线圈 | 强置一串连续逻辑线圈的通断 |
| 16 | 预置多寄存器 | 把具体的二进制值装入一串连续的保持寄存器 |
| 17 | 报告从机标识 | 可使主机判断编址从机的类型及该从机运行指示灯的状态 |
| 18 | (884 和 MICRO 84) | 可使主机模拟编程功能,修改PC状态逻辑 |
| 19 | 重置通信链路 | 发生非可修改错误后,使从机复位 |
QModbusDataUnit 是 Qt Modbus 模块中的一个核心类,用于表示Modbus协议中一次读写操作所涉及的数据单元。如下表所示:
| QModbusDataUnit::RegisterType 枚举值 | Modbus功能码 | 寄存器类型(通俗名称) | 读写属性 |
|---|---|---|---|
| Coils | 01,05,15 | 线圈,位数据(1bit) | 读写 |
| DiscreteInputs | 02 | 离散输入,位数据(1bit) | 只读 |
| InputRegisters | 04 | 输入寄存器,字数据(16bits) | 只读 |
| HodingRegister | 03,06,16 | 保持寄存器,字数据(16bits) | 读写 |
二 Modbus RTU 主站上位机
2.1 界面设计
基于 Qt 设计上位机界面,包括通信方式选择,串口配置,读写配置,设备参数设置,发送/接收数据展示,发送数据和接收数据。具体界面设置如下图所示:
2.2 编码实现
上位机软件主要功能包括串口操作、从站操作以及信息显示三个部分。
2.2.1 串口操作
首先将通信方式设置为 Serial Port,然后配置串口参数,包括串口号、波特率、数据位、校验位、停止位、超时时间和重复次数。其中,串口号通过自动搜索获取当前可用的串口,实现方式如下:
foreach(const QSerialPortInfo& info, QSerialPortInfo::availablePorts()){ ui->comboBoxPort->addItem(info.portName());}串口操作主要是打开串口和关闭串口,具体实现如下:
void MainWindow::on_pushButton_clicked(){ if(m_stop){ if(modbusDevice){ modbusDevice->disconnectDevice(); delete modbusDevice; modbusDevice = nullptr;}int index = ui->cboxConnectType->currentIndex();if(0== index){ modbusDevice = new QModbusRtuSerialMaster(this);//配置串口参数 modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,ui->comboBoxPort->currentText()