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;
    }
相关推荐
Agentic AI人工智能与大数据7 小时前
数据产品运营指南:如何提升用户活跃度?这4个策略让数据产品不再“沉睡”
大数据·ai·产品运营
飞Link8 小时前
开发者必读:2026 欧盟“AI Omnibus”法案达成,技术合规性红线在哪里?
大数据
老纪的技术唠嗑局8 小时前
深度解析 LLM Wiki / Obsidian-Wiki / GBrain:Agent 时代知识的“自组织”与“自进化”
大数据·数据库·人工智能·算法
好赞科技10 小时前
2026年高口碑餐厅预约小程序排行榜:智能就餐新体验一键解锁
大数据·微信小程序
数据智能老司机10 小时前
深入解锁 dbt——Documentation:项目文档与数据文档
大数据
计算机毕业编程指导师10 小时前
【计算机毕设推荐】Python+Hadoop+Spark共享单车数据可视化分析系统 毕业设计 选题推荐 毕设选题 数据分析 机器学习 数据挖掘
大数据·hadoop·python·计算机·数据挖掘·spark·课程设计
计算机毕业编程指导师10 小时前
【计算机毕设】基于Hadoop的共享单车订单数据分析系统+Python+Django全栈开发 毕业设计 选题推荐 毕设选题 数据分析 机器学习 数据挖掘
大数据·hadoop·python·计算机·数据挖掘·spark·django
2601_9561394211 小时前
文体娱媒品牌全案公司哪家强
大数据·人工智能·python
塔望品牌咨询11 小时前
组织效率诊断框架:返工、解释、等待、救火,分别说明了什么
大数据·产品运营
塔能物联运维11 小时前
两相液冷:从“散热”到“控温”,重构高密度算力的热管理系统
大数据·人工智能