4.9 KiB
4.9 KiB
Modbus TCP 服务器模块
基于libmodbus库的Modbus TCP服务器实现,提供完整的Modbus TCP服务器功能和回调机制。
功能特性
- 基于libmodbus的稳定实现
- 支持多客户端并发连接
- 完整的Modbus功能码支持
- 写操作回调机制,支持应用层错误码反馈
- 线程安全的数据访问和更新接口
- 跨平台支持(Windows/Linux)
支持的Modbus功能
读操作(自动处理)
- 读取线圈(0x01)
- 读取离散输入(0x02)
- 读取保持寄存器(0x03)
- 读取输入寄存器(0x04)
写操作(支持回调)
- 写单个线圈(0x05)
- 写单个保持寄存器(0x06)
- 写多个线圈(0x0F)
- 写多个保持寄存器(0x10)
API接口
基本操作
#include "ModbusTCPServer.h"
ModbusTCPServer server;
// 启动服务器
if (server.start(502, 10)) {
// 服务器启动成功
}
// 停止服务器
server.stop();
设置写操作回调
// 设置写线圈回调
server.setWriteCoilsCallback([](uint8_t unitId, uint16_t address, uint16_t quantity, const uint8_t* values) -> ModbusTCPServer::ErrorCode {
// 处理写线圈请求
// unitId: 单元ID
// address: 起始地址
// quantity: 数量
// values: 写入的值
// 返回错误码
return ModbusTCPServer::ErrorCode::SUCCESS;
});
// 设置写寄存器回调
server.setWriteRegistersCallback([](uint8_t unitId, uint16_t address, uint16_t quantity, const uint16_t* values) -> ModbusTCPServer::ErrorCode {
// 处理写寄存器请求
// 检查地址范围、权限等
if (address >= 1000 && address < 2000) {
// 允许写入
return ModbusTCPServer::ErrorCode::SUCCESS;
} else {
// 拒绝写入 - 非法地址
return ModbusTCPServer::ErrorCode::ILLEGAL_DATA_ADDRESS;
}
});
数据更新接口
// 更新单个数据
server.updateCoil(0, true);
server.updateHoldingRegister(100, 1234);
server.updateDiscreteInput(50, false);
server.updateInputRegister(200, 5678);
// 批量更新数据
std::vector<bool> coils = {true, false, true, false};
server.updateCoils(0, coils);
std::vector<uint16_t> registers = {1000, 2000, 3000};
server.updateHoldingRegisters(100, registers);
错误代码
服务器支持标准的Modbus异常代码:
enum class ErrorCode {
SUCCESS = 0, // 成功
ILLEGAL_FUNCTION = 1, // 非法功能码
ILLEGAL_DATA_ADDRESS = 2, // 非法数据地址
ILLEGAL_DATA_VALUE = 3, // 非法数据值
SERVER_FAILURE = 4, // 服务器故障
ACKNOWLEDGE = 5, // 确认
SERVER_BUSY = 6, // 服务器忙
NEGATIVE_ACKNOWLEDGE = 7, // 否定确认
MEMORY_PARITY = 8, // 内存奇偶校验错误
GATEWAY_PATH_UNAVAILABLE = 10, // 网关路径不可用
GATEWAY_TARGET_FAILED = 11 // 网关目标设备响应失败
};
完整使用示例
#include "ModbusTCPServer.h"
#include <iostream>
#include <thread>
#include <chrono>
int main() {
ModbusTCPServer server;
// 设置写操作回调
server.setWriteCoilsCallback([](uint8_t unitId, uint16_t address, uint16_t quantity, const uint8_t* values) {
std::cout << "写线圈请求 - 单元ID: " << (int)unitId
<< ", 地址: " << address
<< ", 数量: " << quantity << std::endl;
return ModbusTCPServer::ErrorCode::SUCCESS;
});
server.setWriteRegistersCallback([](uint8_t unitId, uint16_t address, uint16_t quantity, const uint16_t* values) {
std::cout << "写寄存器请求 - 单元ID: " << (int)unitId
<< ", 地址: " << address
<< ", 数量: " << quantity << std::endl;
// 检查地址范围
if (address < 1000) {
return ModbusTCPServer::ErrorCode::ILLEGAL_DATA_ADDRESS;
}
return ModbusTCPServer::ErrorCode::SUCCESS;
});
// 启动服务器
if (!server.start(502, 10)) {
std::cerr << "启动服务器失败: " << server.getLastError() << std::endl;
return -1;
}
std::cout << "Modbus TCP服务器已启动,端口: 502" << std::endl;
// 定期更新数据
for (int i = 0; i < 100; ++i) {
server.updateHoldingRegister(1000, i);
server.updateCoil(0, i % 2 == 0);
std::this_thread::sleep_for(std::chrono::seconds(1));
}
// 停止服务器
server.stop();
std::cout << "服务器已停止" << std::endl;
return 0;
}
编译说明
依赖
- Qt 5.x 或更高版本
- C++17 编译器
- libmodbus源码(已包含在VrNets模块中)
构建
qmake ModbusTCPServer.pro
make
使用
该模块编译为静态库,在其他项目中包含:
LIBS += -L../Module/ModbusTCPServer -lModbusTCPServer
INCLUDEPATH += ../Module/ModbusTCPServer/Inc
特性说明
多客户端支持
- 支持同时处理多个客户端连接
- 使用select事件驱动模型,单线程处理所有客户端
- 高效的资源利用,避免线程过多的问题
- 线程安全的数据访问
数据存储
- 内部使用libmodbus的mapping结构存储数据
- 支持10000个线圈、离散输入、保持寄存器和输入寄存器
- 所有数据操作都是线程安全的
回调机制
- 写操作会触发用户定义的回调函数
- 回调函数可以返回错误码来拒绝写操作
- 支持异步处理和验证
错误处理
- 完整的错误处理和状态反馈
- 支持标准Modbus异常代码
- 详细的错误信息获取接口