QtModbus - Modbus通信客户端纯Qt代码实现,完全没问题

22 阅读8分钟

QtModbus - Modbus通信客户端

项目简介

QtModbus是一个基于Qt框架开发的Modbus通信客户端应用程序,支持Modbus TCP和Modbus RTU两种协议。项目采用MVC架构设计,提供暗黑风格的用户界面,适用于工业自动化、物联网设备通信等场景。

技术框架

核心技术栈

  • Qt Framework: 5.12.9 (支持C++14标准)
  • Qt Modules:
    • core: Qt核心模块
    • gui: GUI图形界面模块
    • widgets: 窗口部件模块
    • serialbus: Modbus串行总线模块
    • serialport: 串口通信模块
  • 编译器: MSVC (Microsoft Visual C++)
  • 架构模式: MVC (Model-View-Controller)
  • 多线程: 使用QThread实现工作线程,避免阻塞UI

支持的Modbus功能

  • 读取线圈 (功能码 0x01)
  • 读取离散输入 (功能码 0x02)
  • 读取保持寄存器 (功能码 0x03)
  • 读取输入寄存器 (功能码 0x04)
  • 写入单个线圈 (功能码 0x05)
  • 写入单个寄存器 (功能码 0x06)
  • 写入多个线圈 (功能码 0x0F)
  • 写入多个寄存器 (功能码 0x10)

Modbus数据类型说明

数据类型功能码读写权限典型用途
Coils(线圈)01读/05写单/15写多可读可写开关量输出
Discrete Inputs(离散输入)02只读开关量输入
Holding Registers(保持寄存器)03读/06写单/16写多可读可写参数设置、输出值
Input Registers(输入寄存器)04只读传感器数据、测量值

项目结构

QtModbus/
├── QtModbus.pro              # Qt项目文件
├── main.cpp                  # 程序入口
├── modbusconfig.h            # Modbus配置和宏定义
├── build.bat                 # Windows编译脚本
│
├── config/                   # 配置文件目录
│   └── 编译命令.md           # 编译相关说明
│
├── model/                    # 数据模型层 (MVC中的Model)
│   ├── modbusmodel.h         # 数据模型头文件
│   └── modbusmodel.cpp       # 数据模型实现
│
├── view/                     # 视图层 (MVC中的View)
│   ├── mainwindow.h          # 主窗口头文件
│   ├── mainwindow.cpp        # 主窗口实现
│   └── mainwindow.ui         # Qt Designer界面文件
│
├── controller/               # 控制器层 (MVC中的Controller)
│   ├── modbuscontroller.h    # 控制器头文件
│   └── modbuscontroller.cpp  # 控制器实现
│
├── worker/                   # 工作线程层
│   ├── modbusworker.h        # 工作线程头文件
│   └── modbusworker.cpp      # 工作线程实现
│
└── x64/                      # 编译输出目录
    ├── debug/                # Debug版本输出
    │   └── QtModbusd.exe     # Debug可执行文件
    └── release/              # Release版本输出

架构说明

Model层 (model/)
  • ModbusModel: 负责管理Modbus通信相关的数据
    • 连接参数管理(地址、端口、波特率、从站ID等)
    • 寄存器数据存储(保持寄存器、输入寄存器)
    • 线圈数据存储(线圈、离散输入)
    • 连接状态管理
View层 (view/)
  • MainWindow: 提供用户交互界面
    • 暗黑风格UI设计
    • 连接配置界面
    • 数据读写操作按钮
    • 日志显示窗口
    • 数据显示区域
Controller层 (controller/)
  • ModbusController: 协调Model和Worker之间的交互
    • 单例模式设计
    • 管理工作线程
    • 请求队列管理
    • 信号槽机制通信
Worker层 (worker/)
  • ModbusWorker: 在独立线程中执行Modbus通信操作
    • 避免阻塞主界面线程
    • 支持TCP和RTU两种协议
    • 异步通信处理
    • 错误处理和重试机制

编译和运行

环境要求

  • Qt 5.12.9 或更高版本
  • Microsoft Visual C++ 编译器
  • Windows操作系统

编译步骤

方法1: 使用Qt Creator
  1. 使用Qt Creator打开 QtModbus.pro 文件
  2. 选择编译配置 (Debug/Release)
  3. 点击构建按钮进行编译
方法2: 使用命令行
# 运行编译脚本
build.bat

# 或手动执行
qmake QtModbus.pro
nmake  # 或 mingw32-make

运行程序

# Debug版本
cd x64/debug
QtModbusd.exe

# Release版本
cd x64/release
QtModbus.exe

仿真测试

推荐的第三方测试工具

1. Modbus Poll + Modbus Slave (推荐 - 专业调试工具)

特点: 功能完善、界面友好、支持TCP和RTU协议

下载地址: www.modbustools.com/

工具说明:

  • Modbus Poll: 模拟Modbus主站(Master),用于测试从站设备
  • Modbus Slave: 模拟Modbus从站(Slave),用于测试主站设备
  • 支持30天免费试用

使用步骤:

  1. 下载并安装Modbus Slave
  2. 启动程序,选择连接类型 (TCP/IP或Serial)
  3. 配置从站参数:
    • 从站ID: 1 (与QtModbus配置一致)
    • TCP端口: 60000 (TCP模式)
    • 串口: COM2, 波特率: 115200 (RTU模式)
  4. 在寄存器窗口中设置测试数据
  5. 点击"Connection" -> "Connect"启动从站服务
  6. 使用QtModbus连接测试
2. Modbus Simulator (免费)

特点: 免费开源、支持多从站模拟

下载地址: sourceforge.net/projects/mo…

使用步骤:

  1. 下载并安装Modbus Simulator
  2. 配置从站参数
  3. 启动TCP或RTU从站
  4. 使用QtModbus连接测试
3. pymodbus (Python库 - 免费)

特点: 完全免费、可编程、适合自动化测试

安装步骤:

pip install pymodbus

创建测试从站脚本 (test_slave.py):

from pymodbus.server import StartAsyncTcpServer
from pymodbus.datastore import ModbusServerContext, ModbusSlaveContext
from pymodbus.datastore import ModbusSequentialDataBlock

# 创建数据存储
store = ModbusSlaveContext(
    di=ModbusSequentialDataBlock(0, [0]*100),
    co=ModbusSequentialDataBlock(0, [0]*100),
    hr=ModbusSequentialDataBlock(0, [0]*100),
    ir=ModbusSequentialDataBlock(0, [0]*100)
)

context = ModbusServerContext(slaves=store, single=True)

# 启动TCP从站
StartAsyncTcpServer(context=context, address=("127.0.0.1", 502))

运行测试从站:

python test_slave.py
4. libmodbus (C库 - 免费)

特点: 轻量级、高性能、跨平台

下载地址: libmodbus.org/

使用步骤:

  1. 下载并编译libmodbus
  2. 使用示例代码创建从站
  3. 编译并运行从站程序
  4. 使用QtModbus连接测试

测试流程

TCP模式测试
  1. 启动测试从站:
    • 使用Modbus Slave或其他工具启动Modbus TCP从站
    • 监听地址: 127.0.0.1:60000
    • 从站ID: 1
  2. 配置QtModbus:
    • 协议类型: TCP
    • IP地址: 127.0.0.1
    • 端口: 502
    • 从站ID: 1
  3. 执行测试:
    • 点击"连接"按钮
    • 测试读取保持寄存器 (地址: 0, 数量: 10)
    • 测试读取线圈 (地址: 0, 数量: 10)
    • 测试写入单个寄存器 (地址: 0, 值: 1234)
    • 测试写入单个线圈 (地址: 0, 值: true)
    • 测试写入多个寄存器
    • 测试写入多个线圈
  4. 验证结果:
    • 在QtModbus日志窗口查看操作结果
    • 在测试工具中验证数据是否正确更新
RTU模式测试
  1. 准备虚拟串口:
  2. 启动测试从站:
    • 使用Modbus Slave或其他工具启动Modbus RTU从站
    • 串口: COM1
    • 波特率: 115200
    • 数据位: 8
    • 停止位: 1
    • 校验位: None
    • 从站ID: 1
  3. 配置QtModbus:
    • 协议类型: RTU
    • 串口: COM2
    • 波特率: 9600
    • 数据位: 8
    • 停止位: 1
    • 校验位: None
    • 从站ID: 1
  4. 执行测试:
    • 按照TCP模式的测试步骤进行测试

测试检查清单

  • 成功连接到从站设备
  • 成功读取保持寄存器
  • 成功读取输入寄存器
  • 成功读取线圈
  • 成功读取离散输入
  • 成功写入单个寄存器
  • 成功写入单个线圈
  • 成功写入多个寄存器
  • 成功写入多个线圈
  • 正确处理连接失败情况
  • 正确处理超时情况
  • 正确处理非法地址错误
  • 日志信息正确显示

配置说明

默认配置参数

  • TCP端口: 60000
  • RTU波特率: 115200
  • 从站ID: 1
  • 超时时间: 1000ms
  • 重试次数: 3次
  • 最大寄存器数量: 125
  • 最大线圈数量: 2000

地址范围

  • 寄存器地址: 0-65535
  • 线圈地址: 0-65535
  • 从站ID: 1-247

代码规范

  • 遵循Qt C++编码规范
  • 使用Doxygen风格的注释
  • 函数大括号放在下一行
  • 不添加不必要的代码注释
  • 所有日志信息使用中文

版本信息

  • 当前版本: 1.0.0
  • 最后更新: 2026-03-03

已知问题与解决方案

Modbus RTU模式多线程问题

问题描述: 在Qt 5.8 - 5.12版本中,使用QModbusRtuSerialMaster进行多线程操作时,可能会出现以下问题:

  • 程序随机卡死或崩溃
  • 报错 ASSERT failure in processQueue: "response timer active"
  • 报错 ASSERT failure in processQueue: "unexpected state:"

影响范围: 仅影响 RTU串口模式,TCP模式不受影响

根本原因: QModbusRtuSerialMaster类内部定时器状态管理存在缺陷,这是Qt官方的Bug,在Qt 5.13版本中已修复。

解决方案:

  1. 推荐方案:升级Qt版本
    • 升级到Qt 5.13或更高版本(官方已修复此Bug)
  2. 临时解决方案
    • 本项目已在代码中实现RTU模式请求间隔控制(≥500ms)
    • TCP模式无此限制,可快速连续请求
  3. 替代方案
    • 如条件允许,使用TCP模式代替RTU模式

代码改进:

  • 本项目已实现了以下改进:
    • 添加了 initWorker 方法确保 ModbusWorker 对象被正确移动到子线程
    • 修改了 createModbusClient 方法确保 Modbus 客户端对象在子线程中创建
    • RTU模式下自动控制请求间隔≥500ms,避免触发Bug
    • TCP模式无请求间隔限制,可快速连续操作
    • 使用QEventLoop同步等待方式处理请求

参考链接: blog.csdn.net/sbknight/ar…

许可证

本项目仅供学习和研究使用。

联系方式

如有问题或建议,请联系项目维护者。