libmodbusTcp发送自定义功能码

一、modbusTcp的报文结构

cpp 复制代码
TCP ADU结构(最大260字节):
┌──────────────────┬─────────────────────┐
│     MBAP头       │       PDU           │
│     7字节        │  1-253字节          │
└──────────────────┴─────────────────────┘
总长度 = 7 + 253 = 260字节

MBAP头内容:
#pragma pack(push, 1)
typedef struct {
    uint16_t transaction_id;  // 事务标识符
    uint16_t protocol_id;     // 协议标识符(0x0000)
    uint16_t length;          // 后续字节数(PDU长度 + 1)
    uint8_t  unit_id;         // 单元标识符(相当于RTU地址)
} modbus_tcp_header_t;
#pragma pack(pop)

PDU内容:
功能码+数据

二、封装libmodbus为静态库

将最新的libmodbus库编译为静态库并放到指定文件夹,主要涉及下载源码、配置编译环境、执行交叉编译等步骤。下面我为你详细梳理一下流程,并提供一个清晰的步骤表格。

📥 1. 获取源代码

首先,你需要下载libmodbus库的源代码。推荐通过Git获取最新版本,因为某些新版本(如3.1.4及以上)的编译配置可能需要使用autogen.sh脚本生成configure文件,而Git仓库通常包含这些必要的自动化工具脚本

复制代码
git clone git://github.com/stephane/libmodbus.git
cd libmodbus

⚙️ 2. 准备编译环境

在编译前,需要确保你的系统具备必要的编译工具。如果是从Git克隆的代码,这一步是必须的

  • 在Ubuntu/Debian系统上,可以使用以下命令安装:

    sudo apt-get install automake autoconf libtool

  • 执行自动化脚本,生成configure配置文件:

    ./autogen.sh

🔧 3. 配置编译参数

接下来,你需要配置编译参数,以生成静态库并指定安装目录。假设你希望将编译好的静态库安装到 /home/yourusername/mylibs/libmodbus目录下。

在libmodbus源码目录下,执行以下命令

复制代码
# 创建一个目录用于存放编译产出,例如名为 "install"
mkdir -p /home/yourusername/mylibs/libmodbus

# 运行configure脚本进行配置
./configure --enable-static --prefix=/home/yourusername/mylibs/libmodbus

参数说明

  • --enable-static:告诉编译系统生成静态库(.a文件)

  • --prefix=/path/to/your/folder:指定库的安装路径,编译后的文件将存放在此路径下的 libinclude目录中

🛠️ 4. 编译和安装

配置完成后,就可以开始编译并安装了

复制代码
# 编译源码
make

# 将编译好的库和头文件安装到 --prefix 指定的目录中
make install

📁 5. 最终成果

执行完 make install后,你会在之前通过 --prefix指定的文件夹(例如 /home/yourusername/mylibs/libmodbus)中看到以下结构

复制代码
/home/yourusername/mylibs/libmodbus/
├── include/
│   └── modbus/               # 头文件目录
│       ├── modbus.h          # 主要的头文件
│       ├── modbus-version.h
│       ├── modbus-rtu.h
│       └── modbus-tcp.h
└── lib/                      # 库文件目录
    ├── libmodbus.a           # 静态库文件
    ├── libmodbus.la
    └── pkgconfig/

三、发送用户自定义功能码

cpp 复制代码
modbus_t *ctx;
/* 第一位是地址,第二位是功能码,后面是数据内容,无需添加crc校验码,库中会自动添加*/
uint8_t raw_req[] = { 0xFF, 0x64, 0x00, 0x01, 0x0, 0x05 };
int req_length;
uint8_t rsp[MODBUS_TCP_MAX_ADU_LENGTH];
 
ctx = modbus_new_tcp("127.0.0.1", 1502);
if (modbus_connect(ctx) == -1) {
    fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    modbus_free(ctx);
    return -1;
}
 
req_length = modbus_send_raw_request(ctx, raw_req, 6 * sizeof(uint8_t));
modbus_receive_confirmation(ctx, rsp);
 
modbus_close(ctx);
modbus_free(ctx);

出现TCP粘包问题,且数据接收不完整

解决办法:修改libmodbus底层驱动函数,详细的可以看下面的文章

Users functions by demiurg-spb · Pull Request #522 · stephane/libmodbus · GitHub

cpp 复制代码
//response_len为想要接收的数据长度, 不含从站地址和功能码
int send_rc = modbus_send_generic_request(m_ctx, request_data, request_len, *response_len);
    if (send_rc == -1)
    {
        return MB_DRIVER_SEND_CUSTOM_ERR;
    }

    int full_response_len = modbus_receive_confirmation(m_ctx, response_data);
    if (full_response_len == -1)
    {
        return MB_DRIVER_SEND_CUSTOM_ERR;
    }
相关推荐
Ashley_Amanda2 小时前
SAP ABAP 开发全攻略:从核心编程到最佳实践
大数据·数据库·sql
彭思远20062 小时前
以 MapReduce 之力,解锁螺蛳粉销量数据的有序密码
大数据·mapreduce
黎相思3 小时前
附录:ChatSDK使用
大数据·elasticsearch·搜索引擎
geneculture3 小时前
融智学:重构认知与实践的智慧体系
大数据·人工智能·融智学的重要应用·信智序位·人类智力·融智时代(杂志)
泰迪智能科技3 小时前
分享|大数据人工智能实验室合作案例举例
大数据·人工智能·科技
熊文豪3 小时前
时序数据库选型指南:如何为大数据场景选择合适的时序数据库
大数据·数据库·时序数据库·iotdb
RPA机器人就选八爪鱼3 小时前
RPA批量采集抖音评论高效攻略:精准获取用户反馈与市场洞察
大数据·人工智能·机器人·rpa
武汉唯众智创3 小时前
云计算与大数据实训室系列产品介绍
大数据·云计算·云计算实训室·大数据实训室·云计算实验室·云计算大数据·云计算大数据实训室