Modbus最全最简单讲解

B站  :道传科技上位机   观看教程

一、什么是Modbus

Modbus是一种串行通信协议,最初由Modicon公司(现为施耐德电气的一部分)在1979年为使用其PLC(可编程逻辑控制器)而开发。Modbus已成为工业领域内广泛使用的一种通信协议,特别是对于监控和控制系统。Modbus协议支持多种通信方式,包括RTURemote Terminal Unit,远程终端单元模式)、TCP/IPASCII(美国标准信息交换码)等。

备注:C# 调用EasyModbus库      Python 调用 pyModbus

二、什么是ModbusRTU

Modbus RTURemote Terminal Unit)是一种在串行通讯中广泛使用的协议,主要应用于工业领域的设备之间。这个协议是基于主/从(或客户端/服务器)架构,允许主机(通常称为Master)与多个从机(通常称为Slave)进行通信。在Modbus RTU协议中,数据通过二进制形式传输,使得通信更加高效。

三、ModbusRTU报文格式

四、ModbusRTU报文详解

功能码在 Modbus 标准协议中,功能码总共分为三类:公用功能码、自定义功能码、保留功能码。

公用功能码即经过Modbus协会确认,并提供了公开文档的功能码。在文档中被明确定义,确保唯一。自定义功能码为各厂家(用户)自定义的功能码,不保证唯一性。保留功能码是在报文格式不给范的时候使用的一些功能码,现在已经不作为公共使用了。(公用功能码和自定义功能码的区别可以近似对比计算机的熟知端口和注册端口)

读取功能码

01 (0x01): 读线圈状态(Read Coils- 用于读取一组逻辑线圈的当前状态(ON/OFF)。

02 (0x02): 读离散输入状态(Read Discrete Inputs- 用于读取一组离散输入的状态(ON/OFF)。

03 (0x03): 读保持寄存器(Read Holding Registers- 用于读取一组保持寄存器中的二进制内容。

04 (0x04): 读输入寄存器(Read Input Registers- 用于读取一组输入寄存器中的二进制内容。

写入功能码

05 (0x05): 写单个线圈(Write Single Coil- 用于写入单个逻辑线圈的状态(ON/OFF)。

06 (0x06): 写单个寄存器(Write Single Register- 用于写入单个保持寄存器的数据。

15 (0x0F): 写多个线圈(Write Multiple Coils- 用于写入一组逻辑线圈的状态。

16 (0x10): 写多个寄存器(Write Multiple Registers- 用于写入一组保持寄存器的数据。

诊断功能码

08 (0x08): 诊断(Diagnostic- 这组功能码用于诊断通信链路的状态,以及测试和诊断Modbus设备。

特殊功能码

17 (0x11): 报告从机IDReport Slave ID- 返回关于设备的信息,如运行状态和识别信息。

22 (0x16): 屏蔽写寄存器(Mask Write Register- 允许用户修改保持寄存器的内容,而不改变未指定位的内容。

23 (0x17): /写多个寄存器(Read/Write Multiple Registers- 同时进行读取和写入操作。

异常码异常功能码:异常功能码为正常功能码 + 0x80,如写入单个寄存器错误返回异常码为0x86

五、ModbusRTU报文数据举例

读取线圈举例

功能码01H读取Modbus从机中线圈寄存器的状态,可以是单个寄存器,或者多个连续的寄存器.

假设从机地址为01H,读取的线圈寄存器的起始地址为0017H,读取38个寄存器,指令如下所示:

读线圈寄存器指令

01 01 00 17 00 26 0D D4

备注:读取和写入的都是16进制,实际的需要转换为10进制

六、ModbusTCP介绍

Modbus TCP 是基于Modbus RTU协议的扩展,它是一种在以太网上使用的通讯协议。Modbus TCP 报文格式相较于Modbus RTU,主要是在报文的前面增加了一个MBAP头(Modbus Application Protocol header),用于在TCP/IP网络中传输。

七、ModbusTCP报文格式

事务标识符协议标识符长度字段单元标识符四部分即为MBAP头。

八、ModbusTCP报文详解

事务标识符

用于标识请求和响应的对应关系,客户端发起的每个请求都会分配一个唯一的事务标识符,服务器在响应时会使用相同的标识符。在并发请求的环境下,事务标识符尤其重要。事务标识符通常由请求发起端生成,通过递增、随机等不同方式进行生成。

协议标识符

协议标识符用于识别上层协议。在标准的Modbus TCP应用中,这个值被设置为0x0000,表示使用的是Modbus协议。虽然协议标识符通常被设置为0,但它的存在为Modbus TCP提供了扩展的可能性。这意味着在未来,如果需要,Modbus TCP可以支持除了Modbus之外的其他协议,而无需更改现有的架构。

长度字段

表示接下来的单元标识符、功能码和数据的总长度,单位为字节。如字段长度为0x0008,则后续部分长度为8字节。

单元标识符

在纯Modbus TCP网络中,单元标识符通常被设置为0255。这是因为在这样的环境里,IP地址已经足够用来区分不同的设备,单元标识符并不起到区分设备的作用。Modbus TCPRTU/ASCII网关中,一个Modbus TCP请求通过网络发送到一个网关设备,然后网关设备将这个请求转换为Modbus RTUASCII格式,并通过串行通信发送给指定的从机。在这种情况下,单元标识符就是用来告诉网关这个请求应该转发给哪个从机的。

功能码

Modbus RTU相同

九、ModbusTCP报文举例

读取线圈举例

发送报文含义:读取服务器1号从站输出线圈,起始地址为0x13=19,对应地址为00020,线圈数量为0x1B=27,即读取1号从站输出线圈,地址从00020-00046,共27个线圈的状态值。

备注:这里值得注意一下,协议中的起始地址指的是索引,后面的地址指的是具体地址,对于任意一个存储区,索引都是从0开始的,但是对应的具体地址,与存储区是相关的,比如输出线圈,0对应00001;输入线圈,0对应10001;输入寄存器,0对应30001;保持寄存器,0对应40001。

十、ModbusASCLL 简介

Modbus ASCII(美国标准信息交换码)报文格式是Modbus协议的一种变体,它允许设备通过文本可读的格式进行通信。这种格式特别适用于速度不是非常关键的应用场景和那些需要通过人眼检查数据的场合。

### 关于 Modbus 协议的代码实现及解释 #### 1. Modbus RTU 协议简介 Modbus 是一种串行通信协议,最初由 Modicon 公司在 1979 年发明用于可编程逻辑控制器 (PLC) 的通讯。该协议支持多种物理层接口标准,如 RS-232、RS-485 和以太网等。其中最常用的是 Modbus RTU 和 Modbus TCP。 对于 Modbus RTU,在 Linux 环境下通常借助第三方库来简化开发工作流程[^2]。下面将以 Python 中 `pymodbus` 库为例展示如何创建简单的客户端和服务端程序: #### 2. 使用 pymodbus 创建服务端与客户端 ##### 安装依赖项 首先安装必要的Python包: ```bash pip install pymodbus ``` ##### 编写服务器端脚本 这里定义了一个基本的服务端应用程序,它监听来自客户端的数据请求并作出响应。 ```python from pymodbus.server.sync import StartTcpServer from pymodbus.device import ModbusDeviceIdentification from pymodbus.datastore import ModbusSequentialDataBlock, ModbusSlaveContext, ModbusServerContext def run_server(): store = ModbusSlaveContext( di=ModbusSequentialDataBlock(0, [1]*10), co=ModbusSequentialDataBlock(0, [2]*10), hr=ModbusSequentialDataBlock(0, [3]*10), ir=ModbusSequentialDataBlock(0, [4]*10)) context = ModbusServerContext(slaves=store, single=True) identity = ModbusDeviceIdentification() identity.VendorName = 'Pymodbus' identity.ProductCode = 'PM' identity.VendorUrl = 'http://github.com/bashwork/pymodbus/' identity.ProductName = 'Pymodbus Server' identity.ModelName = 'Pymodbus Server' StartTcpServer(context=context, identity=identity) if __name__ == "__main__": run_server() ``` ##### 构建客户端连接到上述服务器 此部分展示了怎样建立一个TCP连接至之前启动的服务端,并读取寄存器中的数据。 ```python from pymodbus.client.sync import ModbusTcpClient as ModbusClient client = ModbusClient('localhost', port=502) client.connect() result = client.read_holding_registers(address=0, count=10, unit=1) print(result.registers) client.close() ``` 以上就是基于 Python 的简单 Modbus RTU/TCP 示例教程。这些例子可以帮助开发者理解 Modbus 基础概念及其实际应用场景下的编码方式。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值