一文搞懂Modbus通讯协议
一、什么是 Modbus 协议
先了解一下几个基本的知识点:
协议
:是进行数据交换和解释信息时所要遵守的一套规则和约定,或者说是通信双方共同遵守的一组规则或标准。(下图是书上的截图)
串行通信
:串行通信是一种计算机通信方式,它在主机与外设以及主机之间的数据传输中起着重要作用。串行通信是指数据按位依次传输的通信方式,每位数据占据固定的时间长度,并使用少数几条通信线路完成系统间的信息交换。在串行通信中,数据被分解为一系列单独的比特(位),并按顺序通过传输线进行传输。每个比特在传输线上占用固定的时间长度,这样接收端就可以按照相同的时序接收并重组这些数据位,从而回复出原始数据。~~(这部分详解在我之前的文章有,可以直接在我主页搜索关键字串口
)*~~ *
Modbus协议
是一种串行通信协议,由Modicon公司(现为施耐德电气Schneider Electric)于1979年发表,旨在实现可编辑逻辑控制器(PLC)之间的通信。
如今,它已经成为工业领域通信协议的业界标准,并且是工业电子设备之间常用的连接方式。
Modbus是主从方式通信,也就是说,不能同步进行通信,总线上每次只有一个数据进行传输,既主机发送,从机应答,主机不发送,总线上就没有数据通信。(半双工通信)
一个总线上只能有一个主机,可以有若干个从机。
Modbus是一种串行通信协议,一种应用层报文传输协议(开源协议)
二、Modbus有什么用
Modbus协议广泛应用于工业控制和自动化领域,可以连接各种设备和控制器,用于实现数据交换、监控和控制。具体包括:
- 工业自动化控制:Modbus被广泛应用于工业自动化控制系统中,用于连接PLC、传感器、执行器等设备,实现监控和控制。Modbus 通常通过 RS-485 总线进行串行通信。
- 智能家居:Modbus协议可以应用于智能家居系统中,用于连接各种传感器和执行器,实现远程控制和检测
- 能源监控:Modbus协议可以用于能源监控系统,连接电表、燃气表、水表等设备,实现能源数据的采集和分析。
- 环境检测:Modbus协议可以应用于环境检监测系统中,连接各种传感器和仪器,监测环境参数如温度、湿度、气压等。
- 智能交通:Modbus可以应用于智能交通系统中,用于连接交通控制设备、车辆检测器等,实现交通信号的控制和管理
总的来说,就是约定了一套设备之间数据交互的规则,用于各种设备之间进行通信。
三、Modbus协议分类详解
modbus分为以下三种协议:
- Modbus-RTU (通常通过串行通信(如 RS-232 或 RS-485)进行传输,采用半双工模式)
- Modbus-TCP (通过以太网进行传输,采用全双工模式)
- Modbus-ASCII ( 通常通过串行通信(如 RS-232 或 RS-485)进行传输,采用半双工模式)
以上三种协议,比较常用的 Modbus-RTU 协议,其次是 Modbus-TCP 协议。
Modbus 是OSI模型第 7 层上的应用层报文传输协议,它在连接至不同类型总线或网络的设备之间提供客户机/服务器通信。
Modbus应用层协议和服务规范主要包含两类:
- 一类是串行链路上的Modbus RTU 和 Modbus ASCII(Modbus 串行链路取决于TIA/EIA 标准:232-F 和 485-A),
- 另一类是TCP/IP 上的Modbus TCP(Modbus TCP/IP 取决于IETF 标准:RFC793 和 RFC791 有关)。
Modbus通信栈示意图如下所示:
1. Modbus-RTU
Modbus-RTU是设备之间通信的常见协议,使用二进制编码和CRC错误校验,Modbus-RTU设备通常使用三种接口进行通信。
RTU 代表“远程终端单元”(Remote Terminal Unit),是一种用于数据采集和控制的设备。Modbus-RTU 是 Modbus 协议在串行通信(如 RS-485)中的实现方式。
数据帧结构
Modbus-RTU 的数据帧由以下几个部分组成:
-
地址域(Slave Address): 1 字节,标识从站(Slave)的地址。地址范围通常是 1 到 247,其中 0 是广播地址。每个从设备在总线上都有唯一的地址,主设备通过这个地址来选择与哪个从设备通信。(地址是以十进制形式进行传输和处理的)
-
功能码(Function Code): 1 字节,指示要执行的操作类型,例如读取寄存器、写入寄存器等。
-
数据域(Data): 1N字节,可变长度,包含与功能码相关的数据。例如,读取寄存器时,数据域包含要读取的寄存器地址和数量。对于写请求,数据域包含要写入的值。
-
校验域(CRC): 2 字节,循环冗余校验(Cyclic Redundancy Check)用于检测数据传输中的错误。CRC 是根据前面的字节计算得出的。发送方计算CRC并附加到消息末尾,接收方收到消息后重新计算CRC并与接收到的CRC进行比较,以验证数据是否正确无误。
常见功能码
Modbus-RTU 定义了多种功能码,用于执行不同的操作。以下是一些常见的功能码:
-
0x01: 读取线圈状态(Read Coil Status)
-
0x02: 读取离散输入状态(Read Discrete Inputs)
-
0x03: 读取保持寄存器(Read Holding Registers)
-
0x04: 读取输入寄存器(Read Input Registers)
-
0x05: 写单个线圈(Write Single Coil)
-
0x06: 写单个寄存器(Write Single Register)
-
0x10: 写多个寄存器(Write Multiple Registers)
数据传输示例
假设我们有一个主设备(如PLC或计算机)和一个从设备(如传感器或控制器),主设备想要读取从设备中保持寄存器(Holding Registers)的值。我们将使用功能码 0x03(读取保持寄存器)来实现这一操作。
请求帧示例(十六进制表示):
01 03 00 00 00 02 B8 0A
响应帧示例(十六进制表示):
01 03 04 12 34 56 78 48 4D
- 01:地址域(1 字节): 0x01,从设备地址
- 03:功能码(1 字节): 0x03,读取保持寄存器
- 04:字节数(1 字节): 0x04,返回4个字节的数据,因为读取了2个寄存器,每个寄存器2字节
- 12 34:数据域:第一个寄存器的值(0x1234)
- 56 78:数据域:第二个寄存器的值(0x5678)
- 48 4D:CRC 校验(2 字节):(根据前面的字节计算得出)
2. Modbus-TCP
Modbus使用以太网进行传输时,设备之间使用网线进行连接。与传统的 Modbus-RTU(串行通信)不同,Modbus-TCP 是无连接的,这意味着每次通信都是独立的,不需要建立和断开连接。
Modbus-TCP 使用 TCP/IP 协议栈进行通信,允许设备通过局域网(LAN)、广域网(WAN)甚至互联网进行数据交换。
全双工通信:与 Modbus-RTU 的半双工通信不同,Modbus-TCP 支持全双工通信,即主设备和从设备可以在同一时间发送和接收数据。这提高了通信效率,特别是在高带宽网络中。
端口号:Modbus-TCP 使用 TCP 端口 502 进行通信。
数据帧结构:Modbus-TCP 的数据帧结构与传统的 Modbus 协议类似,但增加了一些字段来适应 TCP/IP 协议栈。
功能码:Modbus-TCP 支持与 Modbus-RTU 相同的功能码,用于执行各种操作。
3. Modbus-ASCII
Modbus-ASCII 是一种基于文本的通信协议,用于在工业自动化系统中进行设备之间的通信。它是 Modbus 协议的一种变体,主要用于串行通信(如 RS-232 或 RS-485)。Modbus-ASCII 协议的设计目的是在低速通信链路上提供可靠的数据传输,尤其是在噪声环境下。较少使用,主要用于早期或特殊应用。
总结
-
Modbus-RTU 适用于需要高实时性和低成本的短距离串行通信场景,广泛应用于工业自动化领域。
-
Modbus-TCP 适用于需要长距离通信和网络扩展的场景,支持以太网通信,适用于复杂的工业网络和远程监控系统。
-
Modbus-ASCII 适用于简单应用和调试场景,传输效率较低,但易于理解和实现。
进制转换
在计算机科学中,字节(Byte)是一个基本的数据单位,通常由 8 位(Bit)组成。无论是十六进制还是二进制,一个字节都表示相同数量的数据,只是表示方式不同。
-
位是计算机信息的最小单位,它可以是0或1,代表两种状态。
一个位只能表示两个不同的值,即二进制系统中的“0”和“1”。 -
字节通常由8个位组成,因此它可以表示2^8 = 256种不同的值。
例如,一个字节可以表示从0到255的整数,或者是一个ASCII字符等。 -
二进制(Binary)是一种基于2的数值系统,只使用数字0和1。每个二进制数字称为一位(bit),而一串二进制数字可以组成一个更大的单位,比如一个字节(8 bits)。
-
十六进制(Hexadecimal):是一种基于16的数值系统,它使用0-9的数字和A-F的字母来表示16种可能的值。每个十六进制数字可以表示4个二进制位(称为一个“半字节”或“nibble”),所以两个十六进制数字就可以表示一个字节。
在计算机中,所有的数据最终都会被转换成二进制格式进行处理:
1 Byte = 8 Bit // 1 字节等于 8 位
二进制: 1010 1100
十六进制: A C
二进制: 0011 1111
十六进制: 3 F
在二进制中,一个字节由 8 位组成,每位可以是 0 或 1。
在十六进制中,一个字节由 2 个十六进制数字表示,每个十六进制数字对应 4 位二进制数。
示例:
假设在 Modbus-RTU 中,一个寄存器的值为 0x1234(十六进制):
十六进制: 12 34
二进制: 00010010 00110100
在传输过程中,这个寄存器的值会被分成两个字节 0x12 和 0x34 进行传输。
其他解释 https://zhuanlan.zhihu.com/p/715697502
nodejs中modbus-serial实现 https://blog.youkuaiyun.com/zh8706/article/details/130712776