Modbus-RTU 数据帧格式 、报文解析


Modbus协议,首先从字面理解它包括 ModBus两部分,首先它是一种bus,即总线协议,和 I2CSPI类似,总线就意味着有主机,有从机,这些设备在同一条总线上。

Modbus支持单主机,多个从机,最多支持247个从机设备。关于Mod,因为这种协议最早被用在PLC控制器中,准确的说是Modicon公司的PLC控制器,这也是Mod-Bus名称的由来。

后来Modicon被施耐德(Schneider)收购,Modbus协议广泛应用在工业控制器、HMI和传感器上,逐渐被其他厂商接受,成为一种主流的通讯协议,用于和外围设备进行通讯。

报文模型

一个报文就是一帧数据:一串完整的指令数据。
Modbus采用 "Big Endian"编码方式,先发送高位字节,然后是低位字节。

设备地址 功能代码 数据 校验
1* 8bit 1* 8bit N * 8bit 2 * 8bit

功能代码

功能码 功能码名称 可操作元件类型 注释
0x01 读线圈 Y、X、M、SM、S、T、C 读一个或多个位
0x02 读离散量输入 X 读一个或多个位
0x03 读寄存器 D、SD、Z、T、C 读一个或多个字
0x05 写单个线圈 Y、M、SM、S、T、C 写一个位
0x06、0x41 写一个寄存器 D、SD、Z、T、C 写一个字
0x0F 写多个线圈 Y、M、SM、S、T、C 写多个位
0x10、0x43 写多个寄存器 D、SD、Z、T、C 写多个字

读线圈 (0x01 0x02)

  1. 请求帧
设备地址 功能码(01H) 起始地址 读取个数 校验码
H L H L
  1. 响应帧
    如果读取的地址不是8的倍数,剩下的位由0填充(由高位开始填充)。
设备地址 功能码(01H) 读取的个数n (字节数) 读取的数据No.1 ...... 读取的数据No.n 校验码
3. 举例
请求 响应
字段名 16进制 字段名 16进制
功能码 01 功能码01
起始地址 Hi 00 字节计数03
起始地址 Lo 13 输出状态27~20CD
输出数量 Hi 00 输出状态35~286B
输出数量 Lo 13 输出状态38~3605

输出27~20的状态表示为十六进制字节值CD,或二进制1100 1101.输出27是这个字节的MSB(最高有效位),输出20是LSB(最低有效位)

Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
1 1 0 0 1 1 0 1
27 26 25 24 23 22 21 20

在最后的数据字节中,将输出38~36的状态表示为十六进制字节值05,或二进制 0000 0101。用零填充5个剩余高位。

Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
0 0 0 0 0 1 0 1
38 37 36

读寄存器 (0x03 0x04)

  1. 请求帧
设备地址 功能码(03H) 起始地址 读取个数 (N) 校验码
H L H L
  1. 响应帧
设备地址 功能码(03H) 读取的个数2*N 读取的数据No.1 ...... 读取的数据No.n 校验码
H L H L
3. 举例 请求读取寄存器108~110的示例。
请求 响应
字段名 16进制 字段名 16进制
功能码 03 功能码03
起始地址 Hi 00 字节计数06
起始地址 Lo 6B 寄存器值 Hi(108)02
寄存器数量 Hi 00 寄存器值 Lo(108)2B
寄存器数量 Lo 03 寄存器数量 Hi (109) 00
寄存器值 Lo(109)00
寄存器值 Hi(110)00
寄存器值 Lo(110)64

结果为:

寄存器内容值 (十六进制)内容值 (十进制)
寄存器 10802 2B555
寄存器 10900 000
寄存器 11000 64100

写单个线圈 (0x05)

  1. 请求帧
设备地址 功能码(05H) 起始地址 写入的值 校验码
H L H L

注:写入的元件的值为0xFF00(ON,1)或者(0x0000)(OFF,0)。

  1. 响应帧
    响应帧是请求帧的重复。
设备地址 功能码(05H) 起始地址 写入的值 校验码
H L H L
3. 举例
请求 响应
字段名 16进制 字段名 16进制
功能码 05 功能码05
起始地址 Hi 00 起始地址 Hi00
起始地址 Lo AC 起始地址 LoAC
输出值 Hi FF 输出值 HiFF
输出值 Lo 00 输出值 Lo00

写单个寄存器 (0x06 0x41)

  1. 请求帧
设备地址 功能码(06H) 起始地址 写入的值 校验码
H L H L
  1. 响应帧
    响应帧是请求帧的重复。
设备地址 功能码(06H) 起始地址 写入的值 校验码
H L H L
3. 举例 将一个十六进制 00 03写入寄存器2的示例
请求 响应
字段名 16进制 字段名 16进制
功能码 06 功能码06
起始地址 Hi 00 起始地址 Hi00
起始地址 Lo 02 起始地址 Lo02
寄存器值 Hi 00 输出值 Hi00
寄存器值 Lo 03 输出值 Lo03

写多个线圈(0x0F)

  1. 请求帧
设备地址 功能码(0FH) 起始地址 元件个数 字节数 (N) 写入的值No.1 ...... 写入的值No.N 校验码
H L H L
N = 元件个数/8,如果余数不等于0,那么N=N+1。
  1. 响应帧
设备地址 功能码(0FH) 起始地址 元件个数 校验码
H L H L
3. 举例

从线圈20开始写10个线圈的示例。请求的数据内容为2个字节:十六进制CD 01(二进制 1100 1101 0000 0001)。二进制安如下对应于输出。

位:1100110100000001
输出:2726252423222120------------2928
请求 响应
字段名 16进制 字段名 16进制
功能码 0F 功能码0F
起始地址 Hi 00 起始地址 Hi00
起始地址 Lo 13 起始地址 Lo13
输出数量 Hi 00 输出数量 Hi00
输出数量 Lo 0A 输出数量 Lo0A
字节计数 02
输出值 Hi CD
输出值 Lo 01

写多个寄存器(0x10 0x43)

  1. 请求帧
设备地址 功能码(10H) 起始地址 元件个数 (N) 字节数 (2*N) 写入的值No.1 ...... 写入的值No.N 校验码
H L H L H L H L
  1. 响应帧
设备地址 功能码(10H) 起始地址 元件个数 校验码
H L H L
3. 举例

将十六进制00 0A和01 02写入以第2个寄存器开始的两个寄存器的示例。

请求 响应
字段名 16进制 字段名 16进制
功能码 10 功能码10
起始地址 Hi 00 起始地址 Hi00
起始地址 Lo 01 起始地址 Lo01
寄存器数量 Hi 00 寄存器数量 Hi00
寄存器数量 Lo 02 寄存器数量 Lo02
字节计数 04
寄存器值 Hi 00
寄存器值 Lo 0A
寄存器值 Hi 01
寄存器值 Lo 02

错误代码

在这里插入图片描述

你可以使用以下的Python代码来创建一个Minio上传图片的工具类: ```python from minio import Minio from minio.error import ResponseError class MinioUploader: def __init__(self, endpoint, access_key, secret_key, bucket_name): self.endpoint = endpoint self.access_key = access_key self.secret_key = secret_key self.bucket_name = bucket_name def upload_image(self, file_path, object_name): try: minio_client = Minio(self.endpoint, access_key=self.access_key, secret_key=self.secret_key, secure=False) # 检查bucket是否存在,不存在则创建 if not minio_client.bucket_exists(self.bucket_name): minio_client.make_bucket(self.bucket_name) # 上传图片 minio_client.fput_object(self.bucket_name, object_name, file_path) return True, "Image uploaded successfully" except ResponseError as err: return False, f"Error uploading image: {err}" ``` 使用时,你需要提供Minio服务的endpoint、access_key、secret_key以及bucket_name。然后,你可以调用`upload_image`方法来上传图片。该方法接收两个参数:`file_path`表示本地图片文件的路径,`object_name`表示在Minio中保存的对象名称。 以下是一个使用示例: ```python minio_uploader = MinioUploader(endpoint='minio.example.com', access_key='your-access-key', secret_key='your-secret-key', bucket_name='your-bucket-name') success, message = minio_uploader.upload_image('/path/to/image.jpg', 'image.jpg') if success: print(message) else: print(f"Error: {message}") ``` 请确保已经安装了`minio`库,可以使用`pip install minio`来进行安装。此外,根据你实际的Minio配置,需要修改代码中的相关参数。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值