# QtModbus
**Repository Path**: qt-adventure-works/QtModbus
## Basic Information
- **Project Name**: QtModbus
- **Description**: QtModbus是一个基于Qt框架开发的Modbus通信客户端应用程序,支持Modbus TCP和Modbus RTU两种协议。项目采用MVC架构设计,提供暗黑风格的用户界面,适用于工业自动化、物联网设备通信等场景。
- **Primary Language**: C++
- **License**: Not specified
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-06-09
- **Last Updated**: 2026-06-09
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 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: 使用命令行
```bash
# 运行编译脚本
build.bat
# 或手动执行
qmake QtModbus.pro
nmake # 或 mingw32-make
```
### 运行程序
```bash
# Debug版本
cd x64/debug
QtModbusd.exe
# Release版本
cd x64/release
QtModbus.exe
```
## 仿真测试
### 推荐的第三方测试工具
#### 1. Modbus Poll + Modbus Slave (推荐 - 专业调试工具)
**特点**: 功能完善、界面友好、支持TCP和RTU协议
**下载地址**:
**工具说明**:
- **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 (免费)
**特点**: 免费开源、支持多从站模拟
**下载地址**:
**使用步骤**:
1. 下载并安装Modbus Simulator
2. 配置从站参数
3. 启动TCP或RTU从站
4. 使用QtModbus连接测试
#### 3. pymodbus (Python库 - 免费)
**特点**: 完全免费、可编程、适合自动化测试
**安装步骤**:
```bash
pip install pymodbus
```
**创建测试从站脚本** (test\_slave.py):
```python
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))
```
**运行测试从站**:
```bash
python test_slave.py
```
#### 4. libmodbus (C库 - 免费)
**特点**: 轻量级、高性能、跨平台
**下载地址**:
**使用步骤**:
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. **准备虚拟串口**:
- 使用com0com或Virtual Serial Port Driver创建虚拟串口对 (如COM1-COM2)
- 下载地址:
- com0com:
- Virtual Serial Port Driver:
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同步等待方式处理请求
**参考链接**:
## 许可证
本项目仅供学习和研究使用。
## 联系方式
如有问题或建议,请联系项目维护者。