当前位置: 首页 > news >正文

工控领域协议之Modbus

Modbus 是一种通信协议,用于工业自动化领域中的设备之间的通信。它是一种串行通信协议,广泛应用于连接不同设备、传感器和执行器的工业控制系统。 Modbus 在工业控制系统、自动化设备、能源管理系统等领域得到广泛应用。

Modbus 协议的基本特点:

通信方式: Modbus 支持串行通信和以太网通信。串行通信通常使用 RS-232、RS-485 或 RS-422 等标准。

协议类型: Modbus 协议有不同的变体,包括 Modbus RTU(二进制形式)和 Modbus ASCII(ASCII 文本形式)。此外,基于以太网的 Modbus TCP/IP 也是一种常见的变体。

数据帧: Modbus 通信使用数据帧(Frame)进行信息传递。帧包括地址、功能码、数据和错误检测字段。

功能码: Modbus 定义了一系列功能码,用于执行不同的操作。例如,读取保持寄存器、写入单个寄存器等。

寄存器: 数据在 Modbus 中以寄存器的形式存储。有输入寄存器、保持寄存器等不同类型。

主从结构: Modbus 通信通常涉及到主从结构。主设备(Master)发起通信请求,而从设备(Slave)响应请求。

在这里插入图片描述

数据帧

Modbus 通信使用数据帧(Frame)进行信息传递。帧包括地址、功能码、数据和错误检测字段。
在这里插入图片描述

网络架构

每种类型的设备(PLC, HMI,控制面板,驱动程序,运动控制,I/O设备…)都可以使用MODBUS协议发起远程操作。

同样的通信可以在串行线上完成,也可以在以太网TCP/IP网络上完成。网关允许使用MODBUS协议在几种类型的总线或网络之间进行通信
在这里插入图片描述
MODBUS协议定义了三个PDUs.
 MODBUS Request PDU, mb_req_pdu
 MODBUS Response PDU, mb_rsp_pdu
 MODBUS Exception Response PDU, mb_excep_rsp_pdu

Modbus主从通信

Modbus 通信通常涉及到一个主设备(Master)和一个或多个从设备(Slave)。以下是建立 Modbus 通信连接的一般步骤:

主设备(Master)的操作:

确定通信参数: 主设备需要确定与从设备通信时所需的参数,包括通信端口、波特率、奇偶校验等。

选择通信方式: 主设备可以选择串行通信(RS-232、RS-485、RS-422等)或以太网通信(Modbus TCP/IP)。

创建 Modbus 请求帧: 主设备通过构建包含适当功能码和数据的 Modbus 请求帧来发起通信请求。功能码指示所需的操作,例如读取寄存器、写入寄存器等。

发送请求帧: 主设备通过选定的通信方式将请求帧发送到从设备。

等待响应: 主设备等待从设备的响应。响应帧包含所请求的数据或操作的结果。

解析响应: 主设备解析从设备发送的响应帧,提取所需的信息。

从设备(Slave)的操作:

接收请求帧: 从设备通过选定的通信方式接收主设备发送的请求帧。

解析请求: 从设备解析主设备发送的请求帧,确定所需执行的操作和相关参数。

执行操作: 从设备执行主设备请求的操作,例如读取寄存器、写入寄存器等。

创建响应帧: 从设备根据执行结果创建包含响应数据的 Modbus 响应帧。

发送响应帧: 从设备通过选定的通信方式将响应帧发送回主设备。

在通信过程中,主从设备都应该能够处理可能的错误情况。这可能包括超时、通信中断、校验错误等。

modbus协议的主从通信

在 Linux 下使用 C/C++ 实现 Modbus 主从通信涉及到底层的串口或网络通信编程,以及构建 Modbus 请求和响应帧的操作。以下是一个简单的示例,使用串口通信(RS-485)实现 Modbus 主从通信,主设备读取从设备的保持寄存器的例子.

安装 Modbus 库

sudo apt-get install libmodbus-dev

Modbus 从设备代码

从设备代码示例(modbus_slave.cpp)

#include <modbus/modbus.h>int main() {modbus_t *ctx;uint16_t holding_registers[2] = {0x1234, 0xABCD};// Create a new context with Modbus RTU over RS-485ctx = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 1);if (ctx == NULL) {fprintf(stderr, "Unable to create Modbus context\n");return -1;}// Set the Modbus device IDmodbus_set_slave(ctx, 1);// Start the Modbus server (listen for requests)modbus_mapping_t *mb_mapping = modbus_mapping_new(0, 0, 2, 0);modbus_mapping_set_base_address(mb_mapping, 0, 0);modbus_mapping_set_pointer(ctx, mb_mapping);while (1) {// Handle Modbus requestsmodbus_receive(ctx, mb_mapping);modbus_reply(ctx, mb_mapping, 0x01);  // 0x01 is the Modbus function code for reading holding registers}// Clean upmodbus_mapping_free(mb_mapping);modbus_close(ctx);modbus_free(ctx);return 0;
}

Modbus 主设备代码

主设备代码示例(modbus_master.cpp)

#include <modbus/modbus.h>int main() {modbus_t *ctx;uint16_t holding_registers[2];// Create a new context with Modbus RTU over RS-485ctx = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 1);if (ctx == NULL) {fprintf(stderr, "Unable to create Modbus context\n");return -1;}// Set the Modbus device IDmodbus_set_slave(ctx, 1);// Connect to the Modbus serverif (modbus_connect(ctx) == -1) {fprintf(stderr, "Modbus connection failed: %s\n", modbus_strerror(errno));modbus_free(ctx);return -1;}// Read holding registers from the Modbus serverint num_registers = modbus_read_registers(ctx, 0, 2, holding_registers);if (num_registers == -1) {fprintf(stderr, "Modbus read failed: %s\n", modbus_strerror(errno));} else {printf("Holding Register 0: 0x%04X\n", holding_registers[0]);printf("Holding Register 1: 0x%04X\n", holding_registers[1]);}// Disconnect and clean upmodbus_close(ctx);modbus_free(ctx);return 0;
}

编译和运行

# 编译从设备代码
g++ modbus_slave.cpp -o modbus_slave -lmodbus# 编译主设备代码
g++ modbus_master.cpp -o modbus_master -lmodbus# 运行从设备
./modbus_slave# 在另一个终端运行主设备
./modbus_master

实际中需要根据具体设备的 Modbus 协议文档和通信方式进行适当的配置和编码。同时,对于网络通信,可以使用 Modbus TCP/IP,而不是串口通信。

http://www.dtcms.com/a/315205.html

相关文章:

  • prometheus应用CounterGauge
  • prometheus应用demo(一)接口监控
  • 【MySQL04】:基础查询
  • 初识SpringBoot
  • Java计算机网络面试题
  • 【BUUCTF系列】[SUCTF 2019]EasySQL1
  • script标签放在header里和放在body底部里有什么区别?
  • 鸿蒙开发元组
  • 单点登录(SSO)全面解析:原理、实现与应用
  • 中标喜讯 | 安畅检测成功中标海南工信大脑(二期)软件测评服务
  • 基于SpringBoot的OA办公系统的设计与实现
  • docker-compose一键部署Springboot+Vue前后端分离项目
  • 映射公式解常微分方程,偏微分方程
  • JVM-自动内存管理-运行时数据区域
  • createAsyncThunk
  • 结构体数组2-单向链表
  • MySQL详解(一)
  • SAP_MMBASIS模块-选择屏幕变式添加动态字段赋值
  • 如何在AD中快速定位器件?J+C
  • AWS服务分类
  • 人员检测识别中漏检率↓76%:陌讯动态特征融合算法实战解析
  • C++入门自学Day6-- STL简介(初识)
  • AI产品经理手册(Ch6-8)AI Product Manager‘s Handbook学习笔记
  • Vue3+TypeScript项目实战day1——项目的创建及环境配置
  • pytorch 学习笔记(2)-实现一个线性回归模型
  • sqli-labs通关笔记-第30关GET字符注入(WAF绕过 双引号闭合 手工注入+脚本注入两种方法)
  • QCustomplot极坐标系绘制
  • Qt项目模板全解析:选择最适合你的开发起点
  • Gitee:本土化DevOps平台如何助力中国企业实现高效研发协作
  • 水面垃圾清扫船cad【6张】三维图+设计说明书