ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

libmodbus 函数指南:modbus_report_slave_id 获取从站设备描述信息

libmodbus 函数指南:modbus_report_slave_id 获取从站设备描述信息 通信嵌入式物联网【免费下载链接】libmodbusA Modbus library for Linux, Mac OS, FreeBSD and Windows项目地址https://gitcode.com/gh_mirrors/li/libmodbus点击查看免费下载modbus_report_slave_id 是 libmodbus 中用于向 Modbus 从站控制器发送 Report Slave ID功能码 0x11请求、以获取设备描述信息的客户端接口在串口RTU通信场景下尤为常用。通过本文你将掌握该函数的原型、响应数据布局、截断返回值语义、错误处理方式以及如何结合 libmodbus 源码src/modbus.c与单元测试tests/unit-test-client.c写出健壮可用的调用代码。函数原型与基本信息该函数在公开头文件 src/modbus.h 中声明原型如下MODBUS_API int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest);ctx由modbus_new_rtu或modbus_new_tcp等构造的 Modbus 上下文指针max_dest目标缓冲区dest最多可写入的字节数dest用于接收响应的字节缓冲区。从源码实现看src/modbus.c该函数按以下流程工作校验ctx NULL、dest NULL或max_dest 0任一成立即设置errno EINVAL并返回 -1调用后端build_request_basis(ctx, MODBUS_FC_REPORT_SLAVE_ID, 0, 0, req)构造请求帧其中功能码MODBUS_FC_REPORT_SLAVE_ID定义为 0x11见 src/modbus.h源注释明确指出addr 和 count 参数在本功能中不使用因此构造后要减去 4 个字节req_length - 4见 src/modbus.c通过send_msg发送请求再调用_modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION)等待响应并用check_confirmation校验响应一致性从offset header_length 2处开始解析响应体跳过功能码与字节计数字段将最多max_dest字节拷贝到dest。串口/网络适用性该函数仅支持串口Modbus RTU通信下的典型使用。源码注释明确标注only available in serial communicationsrc/modbus.cModbus 协议规范中 Report Slave ID0x11也主要面向串行链路设备。在 TCP 模式下能否收到有效响应取决于对端从站是否实现该功能使用前应对目标设备能力进行评估。响应数据布局从站的响应体不计传输层头与校验按如下顺序排列函数将这段数据原样拷贝到dest偏移字段说明dest[0]Slave ID从站自报的标识号。官方文档明确指出这个唯一 ID实际上并不唯一因此不能依赖它来判断后续数据的封装格式dest[1]Run Indicator Status运行指示器状态0x00 OFF停止运行0xFF ON正在运行dest[2] 起Additional Data各厂商从站特有的附加数据。例如 libmodbus 服务端会返回库版本字符串以 libmodbus 自身实现的从站应答逻辑为例src/modbus.c当收到功能码 0x11 的请求时它会依次写入rsp[rsp_length] _REPORT_SLAVE_ID; /* 180见 src/modbus-private.h */ rsp[rsp_length] 0xFF; /* 运行指示器置为 ON */ memcpy(rsp rsp_length, LMB LIBMODBUS_VERSION_STRING, str_len); /* LMB 版本号 */其中_REPORT_SLAVE_ID定义为 180src/modbus-private.h附加数据为LMB前缀加LIBMODBUS_VERSION_STRING库版本字符串由 src/modbus-version.h.in 生成。也就是说libmodbus 服务端返回的完整响应体形如180 0xFF LMB3.x.x。返回值语义成功返回实际读取到的字节数即响应体长度。截断情况当响应长度超过max_dest时返回的是如果缓冲区足够本应写入的字节数而非实际写入量。因此返回值大于max_dest即表示数据被截断。这一点在实现中体现为拷贝循环受i rc i max_dest双重限制src/modbus.c返回值rc始终是完整响应长度。失败返回 -1 并设置 errno。截断语义的测试验证单元测试 tests/unit-test-client.c 专门验证了这一截断行为/* 设一个标记确保写入未越过限制 */ tab_rp_bits[NB_REPORT_SLAVE_ID - 1] 42; rc modbus_report_slave_id(ctx, NB_REPORT_SLAVE_ID - 1, tab_rp_bits); /* 返回值仍是完整响应长度需占用的字节数 */ ASSERT_TRUE(rc NB_REPORT_SLAVE_ID tab_rp_bits[NB_REPORT_SLAVE_ID - 1] 42, ...);测试中NB_REPORT_SLAVE_ID 2 3 strlen(LIBMODBUS_VERSION_STRING)tests/unit-test-client.c即Slave ID 运行指示器 LMB 版本串。以max_dest NB_REPORT_SLAVE_ID - 1调用时返回值为完整长度NB_REPORT_SLAVE_ID同时缓冲区最后一个字节保持原标记 42 未被覆盖——精准印证了返回值大于 max_dest 表示截断的约定。错误处理EINVAL上下文为 NULL、dest为 NULL或max_dest非正数max_dest 0。其余错误由底层传输决定包括但不限于ETIMEDOUT在响应/字节超时内未收到完整响应ECONNRESET连接被对端重置EMBBADDATA收到无法解析的响应数据底层read()/recv()返回的系统错误码。以上超时相关错误码可见于_modbus_receive_msg的注释src/modbus.c响应超时可通过modbus_set_response_timeout调整。测试 tests/unit-test-client.c 也展示了无响应场景下errno ETIMEDOUT的断言方式。使用示例官方文档给出如下最小示例docs/modbus_report_slave_id.mduint8_t tab_bytes[MODBUS_MAX_PDU_LENGTH]; ... rc modbus_report_slave_id(ctx, MODBUS_MAX_PDU_LENGTH, tab_bytes); if (rc 1) { printf(Run Status Indicator: %s\n, tab_bytes[1] ? ON : OFF); }其中MODBUS_MAX_PDU_LENGTH定义为 253src/modbus.h足以容纳绝大多数从站的应答因此作为max_dest可直接消除截断风险。判断rc 1是为了确保至少取到了运行指示器字段tab_bytes[1]。完整可运行示例结合单元测试的打印逻辑tests/unit-test-client.c可写出更完整的调用#include stdio.h #include string.h #include errno.h #include modbus.h int main(void) { modbus_t *ctx; uint8_t tab_bytes[MODBUS_MAX_PDU_LENGTH]; int rc, i; /* 以串口 RTU 为例/dev/ttyS0波特率 1152008N1 */ ctx modbus_new_rtu(/dev/ttyS0, 115200, N, 8, 1); if (ctx NULL) { fprintf(stderr, 无法创建 RTU 上下文: %s\n, modbus_strerror(errno)); return 1; } if (modbus_connect(ctx) -1) { fprintf(stderr, 连接失败: %s\n, modbus_strerror(errno)); modbus_free(ctx); return 1; } /* 指定目标从站地址 */ modbus_set_slave(ctx, 1); rc modbus_report_slave_id(ctx, MODBUS_MAX_PDU_LENGTH, tab_bytes); if (rc -1) { fprintf(stderr, Report Slave ID 失败: %s\n, modbus_strerror(errno)); } else if (rc MODBUS_MAX_PDU_LENGTH) { printf(警告响应被截断实际长度 %d\n, rc); } else if (rc 1) { printf(Run Status Indicator: %s\n, tab_bytes[1] ? ON : OFF); if (rc 2) { printf(Additional data: ); for (i 2; i rc; i) printf(%c, tab_bytes[i]); printf(\n); } } modbus_close(ctx); modbus_free(ctx); return 0; }该示例同时演示了调用前设置从站地址、对-1失败分支用modbus_strerror(errno)输出错误、对截断返回值做显式检测、以及对附加数据的逐字节字符串打印。编译时需链接 libmodbus 库例如gcc -o report_id report_id.c -lmodbus。小结modbus_report_slave_id向从站发送 0x11 功能码请求返回Slave ID 运行指示器 厂商附加数据三段信息返回值是完整响应长度大于max_dest即为截断信号并非实际拷贝字节数这是与多数读取函数不同的关键语义传入MODBUS_MAX_PDU_LENGTH作为max_dest可规避绝大多数截断场景该功能在串口 RTU 场景下最为常用对 TCP 环境需确认对端设备支持情况参数错误统一返回 -1 并置errno EINVAL网络/链路错误可通过modbus_strerror获取可读描述。赞分享通信嵌入式物联网【免费下载链接】libmodbusA Modbus library for Linux, Mac OS, FreeBSD and Windows项目地址https://gitcode.com/gh_mirrors/li/libmodbus点击查看免费下载相关推荐如何快速获取TikTok设备信息参数Cobalt项目实用指南如何快速获取TikTok设备信息参数Cobalt项目实用指南 Cobalt是一款强大的开源项目旨在帮助用户轻松获取和处理社交媒体内容其中包括从TikTok后端音视频网页爬虫Argo/BootstrapBlazor设备信息获取全面指南Argo/BootstrapBlazor设备信息获取全面指南 在现代Web应用开发中获取设备信息是提升用户体验和实现个性化功能的关键。BootstrapBl前端UI组件设备信息revanced-manager硬件信息获取与设备识别技术设备信息revanced manager硬件信息获取与设备识别技术 引言Android设备信息获取的重要性 在Android应用开发中准确获取设备硬件信息移动开发开发工具上一篇Tiptap编辑器自动完成功能实现智能输入建议的技术下一篇如何5分钟快速上手Flutter Assets Audio Player从零开始构建你的第一个音频播放应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表