MODBUS 协议分析

目录

前言

一、MODBUS协议的主要特点

1.存储区

1.功能码

一、Modbus协议报文

1.Modbus RTU

读取保持寄存器的报文(功能码03)

发送报文

接收报文

写入单个保持寄存器的报文(0x06)

发送报文

接收的报文

校验码

2.Modbus-ASCII

读取保持寄存器的报文(功能码03)

发送报文:

接收报文:

校验码

3.Modbus-TCP

读取保持寄存器的报文(功能码03)

发送报文内容

报文返回的内容


前言

MODBUS是一种用于工业自动化领域的通信协议,用于在不同设备之间传输数据。它最初于1979年由Modicon(现在的施耐德电气)开发,旨在让不同类型的设备能够通过一个共同的通信协议进行通信。


提示:以下是本篇文章正文内容,下面案例可供参考

一、MODBUS协议的主要特点

MODBUS协议可以用于不同类型的设备,包括传感器、执行器、PLC(可编程逻辑控制器)、仪表等工业设备中 MODBUS协议相对简单,易于实现和理解。MODBUS协议使用主从结构,其中一个主节点(主站)与多个从节点(从站)通信。主站发起请求并控制通信,从站响应请求并提供数据。通过功能码(Function Code)和存储区(Memory Area)来指定通信操作以及数据的读取或写入位置。

1.存储区

MODBUS协议的通信本质上就是读取或写入存储区的内容 设备中有着不同区域的存储区 些区域可以包含不同类型的数据  存储区 有线圈 寄存器 线圈只能向单个地址中写入0和1 一般代表通过或者断开,寄存器可以写入数据用于存储16位或32位的整数、浮点数等数据通常用来存储传感器数据、监测数据等,

寄存器和线圈又分为输入线圈,输出线圈,输入寄存器,保持寄存器等,有对应的读写权限。

寄存器名称

读权限

写权限

输入线圈

×

输出线圈

输入寄存器

×

保持寄存器

每个存储区会对应一个 代号 输入线圈 1区 输出线圈 0区 输出寄存器 3区 保持寄存器 4区 每个储存区有相应的地址范围 单个存储区最大的地址范围为65536 地址范围为 一般有5位 和 6位的 如 一区 5位的地址范围就是 1区 1 0000-1 9999 6位的地址范围为 1区 1 00000-1 65536 。

如6位的对应寄存器地址范围: (绝对地址一般在文档手册参数中提供的便于使用者理解理解,mobus报文中使用功能码对应的区号加相对地址+1进行地址的定位查找):

寄存器名称

存储区代号

绝对地址

相对地址

输入线圈

1

100000-165536

00000-65536

输出线圈

0

000000-065536

00000-65536

输入寄存器

3

300000-365536

00000-65536

保持寄存器

4

400000-465536

00000-65536

1.功能码

ODBUS协议中的功能码是用于标识通信中要执行的操作的数值。每个功能码都对应一个特定的操作,如读取数据、写入数据等。以下是一些常见的MODBUS功能码及其对应的操作:

描述

功能码

操作区号

读取输入线圈

0x02

1区

读取输出线圈

0x01

0区

读取输入寄存器

0x04

3区

读取保持寄存器

0x03

4区

写入单个线圈

0x05

0区

写入多个线圈

0x0f

0区

写入单个保持寄存器

0x06

4区

写入多个保持寄存器

0x10

4区

每个功能码都有特定的数据格式和操作规则,使用这些功能码可以在主站和从站之间实现数据的读取、写入和控制。不同的功能码适用于不同的数据类型和通信需求,因此在使用MODBUS协议时,需要根据具体的应用场景选择适当的功能码进行通信。

一、Modbus协议报文

Modbus协议主要有三种类型的报文变体, Modbus RTU Modbus ASCII Modbus TCP。Modbus RTU和Modbus ASCII:都使用类似的帧结构,包括从站地址、功能码、数据以及校验和等字段 一般使用串口行通信传输。Modbus TCP:在以太网的基础上进行传输在TCP/IP协议的基础上,具有自己的错误检测和纠正机制。不需要添加校验码的进行校验。主要使用的Modbus RTU 和Modbus TCP这两种 Modbus ASCII因为报文内容太大用的相对不多

1.Modbus RTU

Modbus RTU使用二进制编码,在串行通信中广泛使用。它采用了紧凑的格式 通信速度比较快。广泛使用在需要较短的通信延迟和高可靠性的应用中。

通过Configure Virtual Serial Port Drive虚拟出两个串口来进行测试 来模拟真实连接。

通过modbus poll 模拟主机进行发送报文 先绑定刚刚虚拟好的串口。

设置功能码 和从机id 从0开始的10个地址长度寄存器的内容

从机使用Modbus Slave 进行模拟进行相同配置

可以看到数据接进行的通信。

将报文信息的内容进行 分解

Tx:154-01 03 00 00 00 0A C5 CD

Rx:155-01 03 14 00 DE 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60 CC

读取保持寄存器的报文(功能码03)

发送报文

从机设备地址+功能码+开始的地址(这里是相对地址是根据功能码来加的 功能码对应区号+开始地址+1) +从开始的地址读取多少个地址 +校验码

从机地址

功能码

开始的地址

地址长度

校验码

01

03

00 00

00 0A

C5 CD

接收报文

从机设备地址+功能码+ 后面的字节长度(当前后面的数据)+寄存器数据(每个寄存器内容占两个字节)+校验码

从机地址

功能码

后面的字节长度

第一个寄存器内容

第二个寄存器内容

第三个寄存器内容

第....个寄存器内容

校验码

01

03

14

00 DE

00 01

00 00

....

60 CC

写入单个保持寄存器的报文(0x06)

Tx:016-01 06 00 02 00 01 E9 CA

Rx:017-01 06 00 02 00 01 E9 CA

发送报文

从机地址

功能码

要修改的寄存器地址

修改的内容

校验码

01

06

00 02

00 01

E9 CA

接收的报文

从机地址

功能码

要修改的寄存器地址

修改的内容

校验码

01

06

00 02

00 01

E9 CA

写入多个寄存器的报文(0x10)

Tx:042-01 10 00 00 00 0A 14 00 0B 00 00 00 00 00 00 00 00 00 0B 00 00 00 00 00 00 00 00 A5 EB

Rx:043-01 10 00 00 00 0A 40 0E     

发送的报文

从机地址

功能码

要修改的开始地址

要修改的地址长度

后面数据的长度

要修改的数据

校验码

01

10

00 00

00 0A

14

00 0B….

A5 EB

校验码

Modbus通信中使用的校验码是循环冗余校验(CRC,Cyclic Redundancy Check),用于验证数据的完整性和准确性。CRC是一种错误检测技术,通过对数据进行计算和比较,可以检测是否有数据损坏或错误。

校验码

Modbus rtu通信中使用的校验码是循环冗余校验(CRC,Cyclic Redundancy Check),用于验证数据的完整性和准确性。CRC是一种错误检测技术,通过对数据进行计算和比较,可以检测是否有数据损坏或错误。

例如使用python计算crc校验码

def calculate_crc(data):
    crc = 0xFFFF #初始化一个16位的CRC寄存器
    for byte in data: #传入的数据中的每一个字节
        crc ^= byte #使用异或运算将CRC寄存器的低8位与当前字节进行异或 将当前字节添加到CRC寄存器中
        for _ in range(8):
            if crc & 0x0001: #检查CRC寄存器的最低位是否为1
                crc >>= 1 #将CRC寄存器向右移动1位,相当于将最低位除去。
                crc ^= 0xA001 #如果最低位为1,则与一个预定义的多项式0xA001进行异或运算。
            else:
                crc >>= 1 #最低位为0,则只将CRC寄存器向右移动1位。
    return crc  #返回CRC校验码

# 要发送的二进制数据
binary_data = b'\x01\x03\x00\x00\x00\x0A'

# 将二进制数据转换为整数列表
data = [byte for byte in binary_data]

# 计算CRC校验码
crc_value = calculate_crc(data)

# 将CRC校验码拆分成高位和低位
crc_low_byte = crc_value & 0xFF
crc_high_byte = (crc_value >> 8) & 0xFF

print("CRC校验码:", hex(crc_low_byte), hex(crc_high_byte))

 

2.Modbus-ASCII

Modbus ASCII协议用的相对会少一些 简单介绍下 使用ASCII码字符来表示数据。与Modbus RTU使用二进制格式不同,Modbus ASCII使用ASCII字符表示二进制数据,这使得它更易于人类阅读和调试,但也导致了通信速度较慢。

在 ASCII模式下,消息以冒号 : 字符开头(ASCII表示为 0x3A)以回车换行对

\r\n (ASCII表示为 0x0D和 0x0A)结尾 中间是有效的数据 在Modbus ASCII通信协议中 ASCII模式下数据以30(ASCI编码0)进行开始,通信的数据是由ASCII字符表示的十六进制值构成的。每个字节(8位)的十六进制值被分为两个部分:高位(hi)和低位(lo)。

读取保持寄存器的报文(功能码03)

Tx:166-3A 30 31 30 33 30 30 30 30 30 30 30 41 46 32 0D 0A

Rx:167-3A 30 31 30 33 31 34 30 30 36 34 30 30 36 34 30 30 37 38 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 41 38 0D 0A

发送报文:

去除头(3a : )和尾 ( 0D 0A )

设备地址

功能码

开始地址h

开始地址l

数据个数h

数据个数l

校验码

30 31

30 33

30 30

30 30

30 30

30 41

46 32

接收报文:

设备地址

功能码

字节数

寄存器内容h 1

寄存器内容l 1

........

校验码

30 31

30 33

31 34

30 30

36 34

.......

41 38

校验码

在 Modbus ASCII 通信协议中,校验码是使用纵向冗余校验(LRC,Longitudinal Redundancy Check)来确保报文的完整性。将报文中的所有连续8位字节相加,忽略任何进位,得到一个8位的二进制值。这个过程中,不考虑报文中的起始“冒号”和结束的换行回车符(CRLF)。

从十六进制数值FF(全1)中减去上一步计算得到的8位值,得到其一的补码(即二进制反码),将得到的一的补码再加1,得到最终的LRC校验值。

3.Modbus-TCP

Modbus TCP报文是在Modbus TCP通信中用于交换数据和命令的结构化格式 报文的格式与Modbus协议有些不同,,因为它嵌套在TCP/IP协议之中 通过以太网进行传输。不需要校验码进行验证。

读取保持寄存器的报文(功能码03)

发送报文内容

47 1e 00 00 00 06 01 03 00 00 00 01

发送的次数+00 00代表TCP协议+后面返回数据的长度+功能码+重哪个地址开始读+读取的内容长度

发送的次数

协议表示

长度

设备的地址

功能码

地址开始

寄存器长度

47 1e

00 00

00 06

01

03

00 00

00 01

报文返回的内容

47 1e 00 00 00 05 01 03 02 0c 95

返回的报文的序列号+ 00 00代表TCP协议+后面数据的长度 +设备的地址 +功能码

+读取的寄存器数量 每两个代表读取一个寄存器数据+读取的数据内容

返回次数

协议表示

长度

设备的地址

功能码

读取数量

寄存器内容

47 1e

00 00

00 05

01

03

02

0c 95

  • 66
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值