Skip to content

三、Modbus 通讯(nrc_modbus.h)

数据结构

ModbusTCPParameter

TCP 通讯参数。

成员类型默认值说明
IPstring"192.168.1.13"Modbus TCP 服务器 IP 地址
portint503Modbus TCP 端口号

ModbusRTUParameter

RTU 通讯参数。

成员类型默认值说明
slaveIdint-从站 ID,范围 [0, 65535]
portint1串口端口号
baudrateint115200波特率
checkBitstring"None"奇偶校验位;"None"(无校验)/ "Even"(偶校验)/ "Odd"(奇校验)
dataBitint8数据位;可选 5、6、7、8
stopBitint1停止位;可选 1、2

ModbusMasterParameter

Modbus 主站参数。

成员类型默认值说明
typestring"TCP"主站类型;"TCP""RTU"
startAddressboolfalse起始地址偏移;false 为地址自动 -1(起始为 1),true 为地址不变(起始为 0)
TCPModbusTCPParameter-TCP 通讯参数(type 为 TCP 时有效)
RTUModbusRTUParameter-RTU 通讯参数(type 为 RTU 时有效)

主站配置

modbus_set_master_parameter

设置主站参数(支持 TCP/RTU,最多 9 个工艺号)。

cpp
Result modbus_set_master_parameter(SOCKETFD socketFd, int id, const ModbusMasterParameter& param);

参数说明:

参数类型说明
socketFdSOCKETFD套接字文件描述符,由 connect_robot 返回
idint工艺号,范围 [1, 9]
paramconst ModbusMasterParameter&主站参数结构体

返回值: Result 结构体,resulttrue 时表示设置成功。

使用示例:

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);

参数说明:

参数类型说明
socketFdSOCKETFD套接字文件描述符
idint工艺号,范围 [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);

参数说明:

参数类型说明
socketFdSOCKETFD套接字文件描述符
idint工艺号,范围 [1, 9]
statusint&输出参数,连接状态;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);

参数说明:

参数类型说明
socketFdSOCKETFD套接字文件描述符
idint工艺号,范围 [1, 9]
addressint起始地址
quantityint读取数量;范围 [1, 2000]
datastd::vector<int>&输出参数,读取到的线圈状态数组;每个元素为 01

返回值: 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);

参数说明:

参数类型说明
socketFdSOCKETFD套接字文件描述符
idint工艺号,范围 [1, 9]
addressint起始地址
quantityint读取数量;范围 [1, 2000]
datastd::vector<int>&输出参数,读取到的输入状态数组;每个元素为 01

返回值: 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);

参数说明:

参数类型说明
socketFdSOCKETFD套接字文件描述符
idint工艺号,范围 [1, 9]
addressint起始地址
quantityint读取数量;范围 [1, 125]
datastd::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);

参数说明:

参数类型说明
socketFdSOCKETFD套接字文件描述符
idint工艺号,范围 [1, 9]
addressint起始地址
quantityint读取数量;范围 [1, 125]
datastd::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);

参数说明:

参数类型说明
socketFdSOCKETFD套接字文件描述符
idint工艺号,范围 [1, 9]
addressint线圈地址
dataint写入值;01

返回值: 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);

参数说明:

参数类型说明
socketFdSOCKETFD套接字文件描述符
idint工艺号,范围 [1, 9]
addressint寄存器地址
dataint写入值;范围 [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);

参数说明:

参数类型说明
socketFdSOCKETFD套接字文件描述符
idint工艺号,范围 [1, 9]
addressint起始地址
dataconst std::vector<int>&写入的线圈值数组;每个元素为 01

返回值: 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);

参数说明:

参数类型说明
socketFdSOCKETFD套接字文件描述符
idint工艺号,范围 [1, 9]
addressint起始地址
dataconst 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_status01H读取线圈状态(位,可读可写)
modbus_read_input_status02H读取输入状态(位,只读)
modbus_read_holding_registers03H读取保持寄存器(16 位,可读可写)
modbus_read_input_registers04H读取输入寄存器(16 位,只读)
modbus_write_signal_coil_status05H写单个线圈
modbus_write_signal_holding_registers06H写单个保持寄存器
modbus_write_multiple_coil_status0FH批量写多个线圈
modbus_write_multiple_holding_registers10H批量写多个保持寄存器

注意事项

  1. 工艺号范围id 参数范围为 [1, 9],最多支持 9 个独立的 Modbus 主站配置
  2. 地址偏移startAddressfalse 时,写入地址会自动减 1;为 true 时地址不变
  3. 读取限制:线圈/输入状态单次最多读取 2000 个,寄存器单次最多读取 125 个
  4. 从站功能:从站操作接口暂未开放
  5. 错误处理:所有函数返回 Result 结构体,需检查 result 字段确认操作是否成功