三、Modbus 通讯(nrc_modbus.h)
数据结构
ModbusTCPParameter
TCP 通讯参数。
| 成员 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| IP | string | "192.168.1.13" | Modbus TCP 服务器 IP 地址 |
| port | int | 503 | Modbus TCP 端口号 |
ModbusRTUParameter
RTU 通讯参数。
| 成员 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| slaveId | int | - | 从站 ID,范围 [0, 65535] |
| port | int | 1 | 串口端口号 |
| baudrate | int | 115200 | 波特率 |
| checkBit | string | "None" | 奇偶校验位;"None"(无校验)/ "Even"(偶校验)/ "Odd"(奇校验) |
| dataBit | int | 8 | 数据位;可选 5、6、7、8 |
| stopBit | int | 1 | 停止位;可选 1、2 |
ModbusMasterParameter
Modbus 主站参数。
| 成员 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| type | string | "TCP" | 主站类型;"TCP" 或 "RTU" |
| startAddress | bool | false | 起始地址偏移;false 为地址自动 -1(起始为 1),true 为地址不变(起始为 0) |
| TCP | ModbusTCPParameter | - | TCP 通讯参数(type 为 TCP 时有效) |
| RTU | ModbusRTUParameter | - | RTU 通讯参数(type 为 RTU 时有效) |
主站配置
modbus_set_master_parameter
设置主站参数(支持 TCP/RTU,最多 9 个工艺号)。
cpp
Result modbus_set_master_parameter(SOCKETFD socketFd, int id, const ModbusMasterParameter& param);参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| socketFd | SOCKETFD | 套接字文件描述符,由 connect_robot 返回 |
| id | int | 工艺号,范围 [1, 9] |
| param | const ModbusMasterParameter& | 主站参数结构体 |
返回值: Result 结构体,result 为 true 时表示设置成功。
使用示例:
cpp
ModbusMasterParameter masterParam;
masterParam.type = "TCP";
masterParam.startAddress = false;
masterParam.TCP.IP = "192.168.1.14";
masterParam.TCP.port = 503;
Result ret = modbus_set_master_parameter(socketFd, 1, masterParam);
if (ret.result) {
// 参数设置成功
}modbus_open_master
打开主站通讯连接。
cpp
Result modbus_open_master(SOCKETFD socketFd, int id);参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| socketFd | SOCKETFD | 套接字文件描述符 |
| id | int | 工艺号,范围 [1, 9] |
返回值: Result 结构体。
说明: 调用前需先通过 modbus_set_master_parameter 设置主站参数。
使用示例:
cpp
Result ret = modbus_open_master(socketFd, 1);modbus_get_master_connection_status
获取主站连接状态。
cpp
Result modbus_get_master_connection_status(SOCKETFD socketFd, int id, int& status);参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| socketFd | SOCKETFD | 套接字文件描述符 |
| id | int | 工艺号,范围 [1, 9] |
| status | int& | 输出参数,连接状态;0 表示未连接,1 表示已连接 |
返回值: Result 结构体。
使用示例:
cpp
int connectStatus = 0;
Result ret = modbus_get_master_connection_status(socketFd, 1, connectStatus);
if (ret.result && connectStatus == 1) {
// Modbus 已连接
}功能码 01H - 读线圈
modbus_read_coil_status
读取从站线圈状态(位操作,可读可写)。
cpp
Result modbus_read_coil_status(SOCKETFD socketFd, int id, int address, int quantity, std::vector<int>& data);参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| socketFd | SOCKETFD | 套接字文件描述符 |
| id | int | 工艺号,范围 [1, 9] |
| address | int | 起始地址 |
| quantity | int | 读取数量;范围 [1, 2000] |
| data | std::vector<int>& | 输出参数,读取到的线圈状态数组;每个元素为 0 或 1 |
返回值: Result 结构体。
使用示例:
cpp
std::vector<int> coilData;
Result ret = modbus_read_coil_status(socketFd, 1, 0, 10, coilData);
if (ret.result) {
for (size_t i = 0; i < coilData.size(); i++) {
printf("Coil %zu: %d\n", i, coilData[i]);
}
}功能码 02H - 读输入状态
modbus_read_input_status
读取从站离散输入状态(位操作,只读)。
cpp
Result modbus_read_input_status(SOCKETFD socketFd, int id, int address, int quantity, std::vector<int>& data);参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| socketFd | SOCKETFD | 套接字文件描述符 |
| id | int | 工艺号,范围 [1, 9] |
| address | int | 起始地址 |
| quantity | int | 读取数量;范围 [1, 2000] |
| data | std::vector<int>& | 输出参数,读取到的输入状态数组;每个元素为 0 或 1 |
返回值: Result 结构体。
使用示例:
cpp
std::vector<int> inputStatus;
Result ret = modbus_read_input_status(socketFd, 1, 100, 16, inputStatus);功能码 03H - 读保持寄存器
modbus_read_holding_registers
读取从站保持寄存器(16 位操作,可读可写)。
cpp
Result modbus_read_holding_registers(SOCKETFD socketFd, int id, int address, int quantity, std::vector<int>& data);参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| socketFd | SOCKETFD | 套接字文件描述符 |
| id | int | 工艺号,范围 [1, 9] |
| address | int | 起始地址 |
| quantity | int | 读取数量;范围 [1, 125] |
| data | std::vector<int>& | 输出参数,读取到的保持寄存器值数组;每个元素范围 [0, 65535] |
返回值: Result 结构体。
使用示例:
cpp
std::vector<int> holdingReg;
Result ret = modbus_read_holding_registers(socketFd, 1, 200, 5, holdingReg);
if (ret.result) {
for (size_t i = 0; i < holdingReg.size(); i++) {
printf("Register %zu: %d\n", i, holdingReg[i]);
}
}功能码 04H - 读输入寄存器
modbus_read_input_registers
读取从站输入寄存器(16 位操作,只读)。
cpp
Result modbus_read_input_registers(SOCKETFD socketFd, int id, int address, int quantity, std::vector<int>& data);参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| socketFd | SOCKETFD | 套接字文件描述符 |
| id | int | 工艺号,范围 [1, 9] |
| address | int | 起始地址 |
| quantity | int | 读取数量;范围 [1, 125] |
| data | std::vector<int>& | 输出参数,读取到的输入寄存器值数组;每个元素范围 [0, 65535] |
返回值: Result 结构体。
使用示例:
cpp
std::vector<int> inputReg;
Result ret = modbus_read_input_registers(socketFd, 1, 300, 8, inputReg);功能码 05H - 写单个线圈
modbus_write_signal_coil_status
写单个线圈状态。
cpp
Result modbus_write_signal_coil_status(SOCKETFD socketFd, int id, int address, int data);参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| socketFd | SOCKETFD | 套接字文件描述符 |
| id | int | 工艺号,范围 [1, 9] |
| address | int | 线圈地址 |
| data | int | 写入值;0 或 1 |
返回值: Result 结构体。
使用示例:
cpp
// 将地址 10 的线圈置为 ON
Result ret = modbus_write_signal_coil_status(socketFd, 1, 10, 1);功能码 06H - 写单个保持寄存器
modbus_write_signal_holding_registers
写单个保持寄存器。
cpp
Result modbus_write_signal_holding_registers(SOCKETFD socketFd, int id, int address, int data);参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| socketFd | SOCKETFD | 套接字文件描述符 |
| id | int | 工艺号,范围 [1, 9] |
| address | int | 寄存器地址 |
| data | int | 写入值;范围 [0, 65535] |
返回值: Result 结构体。
使用示例:
cpp
// 将地址 200 的寄存器写入 9999
Result ret = modbus_write_signal_holding_registers(socketFd, 1, 200, 9999);功能码 0FH - 写多个线圈
modbus_write_multiple_coil_status
批量写入多个线圈状态。
cpp
Result modbus_write_multiple_coil_status(SOCKETFD socketFd, int id, int address, const std::vector<int>& data);参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| socketFd | SOCKETFD | 套接字文件描述符 |
| id | int | 工艺号,范围 [1, 9] |
| address | int | 起始地址 |
| data | const std::vector<int>& | 写入的线圈值数组;每个元素为 0 或 1 |
返回值: Result 结构体。
使用示例:
cpp
std::vector<int> coilValues = {1, 0, 1, 0, 1, 1, 0, 0, 1, 0};
Result ret = modbus_write_multiple_coil_status(socketFd, 1, 20, coilValues);功能码 10H - 写多个保持寄存器
modbus_write_multiple_holding_registers
批量写入多个保持寄存器。
cpp
Result modbus_write_multiple_holding_registers(SOCKETFD socketFd, int id, int address, const std::vector<int>& data);参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| socketFd | SOCKETFD | 套接字文件描述符 |
| id | int | 工艺号,范围 [1, 9] |
| address | int | 起始地址 |
| data | const std::vector<int>& | 写入的寄存器值数组;每个元素范围 [0, 65535] |
返回值: Result 结构体。
使用示例:
cpp
std::vector<int> regValues = {100, 200, 300, 400, 500};
Result ret = modbus_write_multiple_holding_registers(socketFd, 1, 200, regValues);完整使用示例
TCP 主站读写完整流程
cpp
#include "nrc_modbus.h"
void modbus_tcp_example(SOCKETFD socketFd) {
// 1. 设置主站参数(TCP 模式)
ModbusMasterParameter masterParam;
masterParam.type = "TCP";
masterParam.startAddress = false; // 起始地址为 1
masterParam.TCP.IP = "192.168.1.14";
masterParam.TCP.port = 503;
Result ret = modbus_set_master_parameter(socketFd, 1, masterParam);
if (!ret.result) {
printf("设置主站参数失败\n");
return;
}
// 2. 打开主站
ret = modbus_open_master(socketFd, 1);
if (!ret.result) {
printf("打开主站失败\n");
return;
}
// 3. 检查连接状态
int status = 0;
ret = modbus_get_master_connection_status(socketFd, 1, status);
if (ret.result && status == 1) {
printf("Modbus TCP 连接成功\n");
}
// 4. 读线圈(功能码 01H)
std::vector<int> coilData;
ret = modbus_read_coil_status(socketFd, 1, 0, 10, coilData);
if (ret.result) {
printf("读取线圈成功: ");
for (int v : coilData) printf("%d ", v);
printf("\n");
}
// 5. 写单个线圈(功能码 05H)
ret = modbus_write_signal_coil_status(socketFd, 1, 3, 1);
// 6. 读保持寄存器(功能码 03H)
std::vector<int> holdingReg;
ret = modbus_read_holding_registers(socketFd, 1, 200, 5, holdingReg);
if (ret.result) {
printf("读取保持寄存器成功: ");
for (int v : holdingReg) printf("%d ", v);
printf("\n");
}
// 7. 写多个保持寄存器(功能码 10H)
std::vector<int> writeReg = {1000, 2000, 3000};
ret = modbus_write_multiple_holding_registers(socketFd, 1, 400, writeReg);
}RTU 主站配置示例
cpp
ModbusMasterParameter rtuParam;
rtuParam.type = "RTU";
rtuParam.startAddress = false;
rtuParam.RTU.slaveId = 1;
rtuParam.RTU.port = 2;
rtuParam.RTU.baudrate = 115200;
rtuParam.RTU.checkBit = "Even";
rtuParam.RTU.dataBit = 8;
rtuParam.RTU.stopBit = 1;
Result ret = modbus_set_master_parameter(socketFd, 2, rtuParam);Modbus 功能码汇总
| 函数 | 功能码 | 操作类型 | 说明 |
|---|---|---|---|
modbus_read_coil_status | 01H | 读 | 读取线圈状态(位,可读可写) |
modbus_read_input_status | 02H | 读 | 读取输入状态(位,只读) |
modbus_read_holding_registers | 03H | 读 | 读取保持寄存器(16 位,可读可写) |
modbus_read_input_registers | 04H | 读 | 读取输入寄存器(16 位,只读) |
modbus_write_signal_coil_status | 05H | 写 | 写单个线圈 |
modbus_write_signal_holding_registers | 06H | 写 | 写单个保持寄存器 |
modbus_write_multiple_coil_status | 0FH | 写 | 批量写多个线圈 |
modbus_write_multiple_holding_registers | 10H | 写 | 批量写多个保持寄存器 |
注意事项
- 工艺号范围:
id参数范围为 [1, 9],最多支持 9 个独立的 Modbus 主站配置 - 地址偏移:
startAddress为false时,写入地址会自动减 1;为true时地址不变 - 读取限制:线圈/输入状态单次最多读取 2000 个,寄存器单次最多读取 125 个
- 从站功能:从站操作接口暂未开放
- 错误处理:所有函数返回
Result结构体,需检查result字段确认操作是否成功