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;
    }
相关推荐
zgl_200537796 小时前
ZGLanguage 解析SQL数据血缘 之 Python + Echarts 显示SQL结构图
大数据·数据库·数据仓库·hadoop·sql·代码规范·源代码管理
潘达斯奈基~7 小时前
万字详解Flink基础知识
大数据·flink
极客先躯7 小时前
如何自动提取Git指定时间段的修改文件?Win/Linux双平台解决方案
linux·git·elasticsearch
zandy101110 小时前
从 Workflow 到 Agent 模式!衡石多智能体协同架构,重新定义智能 BI 底层逻辑
大数据·信息可视化·架构
Elastic 中国社区官方博客10 小时前
Elastic:DevRel 通讯 — 2026 年 1 月
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
萤丰信息10 小时前
从 “钢筋水泥” 到 “数字神经元”:北京 AI 原点社区重构城市进化新逻辑
java·大数据·人工智能·安全·重构·智慧城市·智慧园区
驾数者11 小时前
Flink SQL容错机制:Checkpoint与Savepoint实战解析
大数据·sql·flink
千汇数据的老司机11 小时前
靠资源拿项目VS靠技术拿项目,二者的深刻区分。
大数据·人工智能·谈单
Elastic 中国社区官方博客13 小时前
jina-embeddings-v3 现已在 Elastic Inference Service 上可用
大数据·人工智能·elasticsearch·搜索引擎·ai·jina
Elastic 中国社区官方博客13 小时前
使用 jina-embeddings-v3 和 Elasticsearch 进行多语言搜索
大数据·数据库·人工智能·elasticsearch·搜索引擎·全文检索·jina