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;
    }
相关推荐
子榆.27 分钟前
CANN 性能分析与调优实战:使用 msprof 定位瓶颈,榨干硬件每一分算力
大数据·网络·人工智能
新芒38 分钟前
暖通行业两位数下滑,未来靠什么赢?
大数据·人工智能
忆~遂愿1 小时前
CANN ATVOSS 算子库深度解析:基于 Ascend C 模板的 Vector 算子子程序化建模与融合优化机制
大数据·人工智能
chian-ocean1 小时前
百万级图文检索实战:`ops-transformer` + 向量数据库构建语义搜索引擎
数据库·搜索引擎·transformer
艾莉丝努力练剑2 小时前
【Linux:文件】Ext系列文件系统(初阶)
大数据·linux·运维·服务器·c++·人工智能·算法
倒流时光三十年3 小时前
SpringBoot 数据库同步 Elasticsearch 性能优化
数据库·spring boot·elasticsearch
lili-felicity3 小时前
CANN异步推理实战:从Stream管理到流水线优化
大数据·人工智能
2501_933670794 小时前
2026 高职大数据专业考什么证书对就业有帮助?
大数据
xiaobaibai1534 小时前
营销自动化终极形态:AdAgent 自主闭环工作流全解析
大数据·人工智能·自动化
星辰_mya4 小时前
Elasticsearch更新了分词器之后
大数据·elasticsearch·搜索引擎