一.Modbus基本概念
-
历史背景:由Modicon公司(现施耐德电气)于1979年推出,最初用于PLC通信,现已成为开放标准。
-
核心作用:实现主从设备间简单高效的数据传输,如读取传感器数据或控制执行器。
-
主要特点:
-
主从架构:单主设备(如工控机)控制多个从设备(如传感器、PLC)。
-
协议简单:基于寄存器地址直接读写,易于实现。
-
跨平台支持:支持串口(RS-232/RS-485)和以太网(TCP/IP)。
-
二.通讯模式
1.报文帧格式
-
Modbus RTU:
-
数据格式:二进制编码,紧凑高效。
-
校验方式:CRC循环冗余校验。
-
适用场景:工业现场总线(如RS-485网络)。
-
-
Modbus ASCII:
-
数据格式:ASCII字符可读性高,但传输效率较低。
-
校验方式:LRC纵向冗余校验。
-
适用场景:调试或低速通信环境。
-
-
Modbus TCP:
-
基于TCP/IP:通过以太网传输,端口号502。
-
帧结构:在Modbus RTU基础上添加MBAP报文头,包含事务标识符等字段。
-
2.通信介质
· 串口通讯 :232/485/422
· 以太网:TCP/IP和UDP/IP
3.协议的分类
-
ModbusRTU 协议 :Modbus RTU(Remote Terminal Unit)协议是一种在串行通信中常用的协议格式。它采用二进制编码,具有较高的数据密度,适合在可靠性较高的串行链路(如 RS-232、RS-485)上传输数据。RTU 协议使用校验和(CRC)来确保数据的完整性,数据传输效率较高,在工业自动化领域应用广泛,尤其适用于对数据传输速度要求较高的场景。
-
ModbusASCII 协议 :Modbus ASCII(American Standard Code for Information Interchange)协议也是用于串行通信的 Modbus 协议变体。它采用 ASCII 字符编码,将数据转换为 ASCII 字符后再进行传输。这种编码方式便于人类阅读和调试,但数据传输效率相对 RTU 协议较低。ASCII 协议通常用于对数据传输可靠性要求极高,或通信链路质量较差的环境,因为它可以更好地抵抗通信噪声的干扰。
-
ModbusRTUOverTCP 协议 :该协议是将 Modbus RTU 帧封装到 TCP/IP 协议中进行传输。它结合了 RTU 协议的数据传输效率和 TCP/IP 协议的网络传输能力,使得 Modbus 协议能够在以太网或互联网上进行通信,扩展了 Modbus 协议的应用范围,适用于基于 TCP/IP 网络的工业自动化系统集成。
-
ModbusRTUOverUDP 协议 :与 ModbusRTUOverTCP 类似,但使用的是 UDP/IP 协议进行传输。UDP 是一种无连接的传输层协议,相比 TCP,它不保证数据的可靠传输,但具有较低的传输延迟。因此,ModbusRTUOverUDP 协议适用于对实时性要求较高,且网络环境相对可靠(如局域网内)的 Modbus 应用场景。
-
ModbusASCIIOverTCP 协议 :该协议是将 Modbus ASCII 帧封装到 TCP/IP 协议中进行传输。它结合了 ASCII 协议的可读性和 TCP/IP 协议的网络传输能力,便于在基于 TCP/IP 网络的环境中进行 Modbus 通信,同时也具有较好的调试和维护性。
-
ModbusASCIIOverUDP 协议 :与 ModbusASCIIOverTCP 类似,但使用 UDP/IP 协议进行传输。适用于对实时性要求较高且网络环境较好的场景,同时保留了 ASCII 协议易于阅读和调试的特点。
-
ModbusTCP 协议 :ModbusTCP 协议是 Modbus 协议在 TCP/IP 网络上的实现,直接在 TCP/IP 协议的基础上进行通信,无需像 ModbusRTUOverTCP 或 ModbusASCIIOverTCP 那样对帧进行额外的封装。它具有简单、高效的特点,是目前在以太网环境中应用最广泛的 Modbus 协议之一,广泛应用于工业自动化、楼宇自动化等领域,用于连接各种智能设备和控制系统。
-
ModbusUDP 协议 :ModbusUDP 协议则是 Modbus 协议在 UDP/IP 网络上的实现,使用 UDP 协议进行数据传输。与 ModbusTCP 相比,它具有较低的通信开销和延迟,适用于对实时性要求较高且网络环境可靠的场景,如在局域网内进行高速数据采集和控制。
三.Modbus调试软件使用
ModbusPoll:Modbus主站或Modbus客户端。
ModbusSlave:Modbus从站或Modbus服务器。
ModbusPoll和ModbusSlave软件下载地址:
VSPD: 全称是Virtual Serial Port Driver 是一个虚拟串口软件。
软件下载地址:
举例说明:
首先,我们使用VSPD创建虚拟串口出来。
然后分别在主从软件里面连接到这个串口。
我们在表格里面修改数据,打开实时监控画面,就可以看见数据的交互了。
四.Modbus协议存储区说明
Modbus协议存储分为一下类型:
-
输入寄存器(Input Registers)
-
这些寄存器是只读的,用于存储从输入设备(如传感器等)获取的数据。例如,在一个温度监测系统中,温度传感器将采集到的温度数据存储输入在寄存器中。输入寄存器的地址范围通常从 30001 开始(具体地址编号可能因不同的 Modbus 实现而有所差异),每个寄存器的大小一般为 16 位。
-
-
保持寄存器(Holding Registers)
-
保持寄存器是读写型的寄存器,用于存储应用程序数据,这些数据可以通过网络读取和修改。它主要用于参数配置、控制指令等。比如在一个电机控制系统中,可以通过保持寄存器来发送电机启动、停止命令,或者设置电机的转速等参数。其地址范围一般从 40001 开始,每个寄存器大小也是 16 位。
-
-
线圈(Coils)
-
线圈用于存储的输出位(布尔值)数据,可以被置位(1)或复位(0)。它就像是一个开关状态的存储位置。例如在控制继电器的场景下,如果要控制继电器的吸合(相当于开关闭合,值为 1)和释放(相当于开关断开,值为 0),就可以使用线圈来存储这个状态。线圈的地址范围通常从 00001 开始。
-
-
离散输入(Discrete Inputs)
-
离散输入用于存储输入的位(布尔值)数据,它是只读的。这就好比是一个数字输入点,用于接收简单的开关信号。例如在检测一个门禁系统的门是否关闭这个场景中,门限位开关的状态(门关好是 1,门未关好是 0)就可以存储在离散输入寄存器中。地址范围一般从 10001 开始。
Modbus存储区有哪几种?
-
只读 | 线圈 | 输入线圈 |
读写 | 线圈 | 输出线圈 |
只读 | 寄存器 | 输入寄存器 |
读写 | 寄存器 | 输出寄存器 |
Modbus存储区代号有哪些?
输入线圈 | 1区 |
输出线圈 | 0区 |
输入寄存器 | 3区 |
输出寄存器 | 4区 |
Modbus 协议存储区说明
-
Modbus 存储区范围 :Modbus 规定每个存储区的最大范围是 65536。
-
PLC 地址 :不同 PLC 厂商有自己的地址表示方式,如西门子 MW100 DB1.DBDO、三菱 D0 X0 Y0、欧姆龙 D0 W0 等,其绝对地址=区号+相对地址。
-
Modbus 地址 :绝对地址=区号+(相对地址+1)。输出寄存器的第一个绝对地址是 40001。
存储区分类及地址范围
存储区有输入线圈、输出线圈、输入寄存器、保持寄存器。
长地址模型
-
输入线圈 : 1 区,绝对地址范围 100001-165536,相对地址范围 0-65535。
-
输出线圈 : 0 区,绝对地址范围 000001-065536,相对地址范围 0-65535。
-
输入寄存器 :3 区,绝对地址范围 300001-365536,相对地址范围 0-65535。
-
保持寄存器 :4 区,绝对地址范围 400001-465536,相对地址范围 0-65535。
短地址模型
-
输入线圈 : 1 区,绝对地址范围 10001-19999,相对地址范围 0-9998。
-
输出线圈 : 0 区,绝对地址范围 00001-09999,相对地址范围 0-9998。
-
输入寄存器 :3 区,绝对地址范围 30001-39999,相对地址范围 0-9998。
-
保持寄存器 :4 区,绝对地址范围 40001-49999,相对地址范围 0-9998。
地址模型选择
若数据使用量不大,可选用短地址模型;反之,若数据量较大,则使用长地址模型。
相对地址和绝对地址
-
一般在人为交流或说明文档中使用绝对地址。
-
通常在协议报文中使用相对地址,因为通过功能码可知道是哪个存储区,结合相对地址就能确定具体的数据位置。
五.Modbus协议功能码说明
1.为什么会有功能码?
· 协议的目的是为了数据传输
· 已经确定好存储区,存储区会存储不同的数据类型
· 会有很多种不同的行为
· 我们给每种行为指定一个代号,那么这个代号就是功能码
·功能码其实就是行为的代号
2.Modbus通信有什么行为?
·1)读取输入线圈
-
目的 :了解外部输入设备的状态,如开关、传感器等的信号。
-
功能码 :02
-
数据流向 :从 PLC(或远程设备)的输入线圈读取数据到上位机。
-
特点 :读取的是只读的离散输入状态,用于监控外部输入状态变化。
2)读取输出线圈
-
目的 :获取当前输出设备的控制状态,如继电器的吸合、电机的启停等。
-
功能码 :01
-
数据流向 :从 PLC(或远程设备)的输出线圈读取数据到上位机。
-
特点 :读取的是可写的线圈状态,用于确认当前的输出控制情况。
3)读取输入寄存器
-
目的 :获取外部输入设备的模拟量数据,如温度、压力、流量等传感器采集的数值。
-
功能码 :04
-
数据流向 :从 PLC(或远程设备)的输入寄存器读取数据到上位机。
-
特点 :读取的是只读的寄存器数据,用于监控模拟量输入的变化。
4)读取输出寄存器
-
目的 :了解当前设备的输出参数设置或保持寄存器中的数据。
-
功能码 :03
-
数据流向 :从 PLC(或远程设备)的保持寄存器读取数据到上位机。
-
特点 :读取的是可读写的寄存器数据,用于查看参数配置或输出数据的状态。
5)写入输出线圈
-
目的 :控制外部输出设备的开关状态,如控制继电器的吸合与释放、指示灯的亮灭等。
-
功能码 :05(写单个线圈)、15(写多个线圈)
-
数据流向 :从上位机写入数据到 PLC(或远程设备)的输出线圈。
-
特点 :将控制指令写入线圈,实现对输出设备的直接控制。
6)写入输出寄存器
-
目的 :修改设备的参数设置、发送控制指令或更新保持寄存器中的数据。
-
功能码 :06(写单个寄存器)、16(写多个寄存器)
-
数据流向 :从上位机写入数据到 PLC(或远程设备)的保持寄存器。
-
特点 :更新可读写寄存器中的数据,用于参数调整或发送批量控制信息。
3.Modbus常用的功能码有那些?
1.读取功能码
-
读取输出线圈(0x01)
-
功能 :用于读取输出线圈的开关状态,了解外部输出设备(如继电器、电机等)的控制状态。
-
数据流向 :从 PLC(或远程设备)的输出线圈读取数据到请求数据的设备(如上位机)。
-
应用场景 :在监控系统中,上位机可以通过此功能码读取 PLC 控制的继电器是否吸合、电机是否启动等状态信息。
-
-
读取输入线圈(0x02)
-
功能 :用于读取输入线圈的状态,获取外部输入设备(如开关、传感器等)的信号状态。
-
数据流向 :从 PLC(或远程设备)的输入线圈读取数据到请求数据的设备。
-
应用场景 :如读取紧急停止按钮的状态、传感器的触发状态等,以便及时响应输入设备的变化。
-
-
读取输出寄存器(0x03)
-
功能 :读取保持寄存器中的数据,这些数据可以是设备的参数设置、控制指令或输出数据。
-
数据流向 :从 PLC(或远程设备)的保持寄存器读取数据到请求数据的设备。
-
应用场景 :读取电机的转速设置、温度控制器的设定值等参数,用于监控设备的运行参数和配置。
-
-
读取输入寄存器(0x04)
-
功能 :读取输入寄存器中的数据,这些数据通常是由输入设备(如传感器)采集到的模拟量数据。
-
数据流向 :从 PLC(或远程设备)的输入寄存器读取数据到请求数据的设备。
-
应用场景 :读取温度传感器、压力传感器、流量计等输入设备采集到的数值,用于实时监控和数据采集。
-
2.写入功能码
-
写入单个线圈(0x05)
-
功能 :向单个输出线圈写入状态值(0 或 1),用于控制外部输出设备的开关状态。
-
数据流向 :从请求数据的设备写入数据到 PLC(或远程设备)的输出线圈。
-
应用场景 :控制继电器的吸合与释放、指示灯的亮灭、阀门的开闭等设备的开关控制。
-
-
写入单个寄存器(0x06)
-
功能 :向单个保持寄存器写入数据,用于修改设备的参数设置或发送控制指令。
-
数据流向 :从请求数据的设备写入数据到 PLC(或远程设备)的保持寄存器。
-
应用场景 :设置电机的转速、修改温度控制器的设定值、发送设备的控制指令等。
-
-
写入多个线圈(0x0F)
-
功能 :向多个输出线圈写入状态值(0 或 1),批量控制多个外部输出设备的开关状态。
-
数据流向 :从请求数据的设备写入数据到 PLC(或远程设备)的输出线圈。
-
应用场景 :同时控制多个继电器的吸合与释放、批量控制多个指示灯的亮灭等场景,提高通信效率。
-
-
写入多个寄存器(0x10)
-
功能 :向多个保持寄存器写入数据,用于批量修改设备的参数设置或发送批量控制指令。
-
数据流向 :从请求数据的设备写入数据到 PLC(或远程设备)的保持寄存器。
-
应用场景 :同时设置多个电机的转速、批量修改多个设备的参数、发送批量控制指令等,减少通信次数,提高数据传输效率。
-
4.Modbus其他的功能码——异常&自定义
异常回应功能码
-
目的 :当从设备无法处理请求时,会返回异常响应给主设备,其功能码是请求功能码的最高有效字节(MSB)被设置为 1,例如,若请求功能码是 0x03,则对应的异常响应功能码是 0x83。用于向主设备报告从设备遇到的错误情况,帮助主设备了解通信失败的原因。
-
常见的异常功能码含义 :
-
0x81(非法功能) :从设备无法识别该请求功能码。这可能是由于主设备发送了错误的功能码,或者从设备不支持该功能码,类似于请求了一个不存在的功能,设备无法理解应该如何响应。
-
0x82(非法数据地址) :从设备无法访问请求的数据,原因可能是请求的寄存器地址超出范围,或者地址不存在。就像想要访问一个不存在的文件路径,系统无法找到对应的资源。
-
0x83(非法数据值) :主设备请求的值超出从设备可接受的范围,或者写入值不符合要求。例如尝试写入一个超过寄存器存储能力的数值,或者尝试设置一个设备不支持的参数值,类似于输入一个不符合格式要求的数据。
-
0x84(从设备故障) :从设备发生故障,无法执行请求的操作。这可能是由于设备硬件故障、软件问题或通信错误等原因导致,就像设备突然出现故障,无法正常运行一样。
-
0x85(从设备忙) :从设备正在进行其他任务,暂时无法响应请求。设备在执行某些长操作或处理其他请求时,无法同时处理新的请求,需要稍后再试。
-
自定义功能码
-
目的 :在某些特定的应用场景中,用户可能需要实现一些特殊的功能,这些功能无法通过标准功能码来完成。自定义功能码允许用户根据实际需求定义新的功能码,以扩展 Modbus 协议的功能。
-
使用方式 :自定义功能码通常使用 0x0B(广播写入)、0x11 - 0x16(未定义)、0x1C - 0x7F(未定义)等未被分配的功能码范围。用户可以在这些范围内定义自己所需的特殊功能,如设备特定的配置、复杂的业务逻辑处理等。不过,这些自定义功能码需要在通信双方的设备中进行定义和实现,以确保双方能够正确理解和处理这些功能码。
六.ModbusRTU功能码的格式
1.通用报文帧格式
设置地址 | 功能代码 | 数据格式 | CRC校验 |
1字节 | 1字节 | N字节 | 1字节 |
·设置地址 :要和那个通讯。
· 功能码 :要做什么事情。
·数据部分 :
1)读取发送: 开始地址+数据数量
2)读取接收: 字节计数+具体数据
3)写入单发送: 具体地址+写入数据
4)写入单接收: 具体地址+写入数据
5)写入多发送:开始地址+写入数量+写入数据
6)写入多接收: 开始地址+写入数量
·校验部分 :crc16
2.校验部分注意点
1)上面的校验和串口的奇/偶/无校验没有关系
2)校验可以保证数据的准确性
3.常用功能码不同类型的报文格式
首先,我们在这里设置两虚拟端口。
1)01H功能码读取输出线圈
发送报文格式 | 从站地址 | 功能码 | 开始线圈地址 | 线圈数量 | CRC校验 |
接收报文格式 | 从站地址 | 功能码 | 字节计数 | 数据 | CRC校验 |
举例: 读取线圈测试——读取1号站点从10开始的20个线圈的值
主从站进行设置。
然后,设置线圈的数量,及读取的个数位置。
最终,可以获得的结果。
2)02H功能码读取输出线圈
发送报文格式 | 从站地址 | 功能码 | 开始线圈地址 | 线圈数量 | CRC校验 |
接收报文格式 | 从站地址 | 功能码 | 字节计数 | 数据 | CRC校验 |
举例:读取输出线圈——读取5号站点从20开始的10个线圈
主从站进行设置。
然后,设置线圈的数量,及读取的个数位置。
最终,可以获得的结果。
3)03H功能码读取输出寄存器
发送报文格式 | 从站地址 | 功能码 | 开始寄存器地址 | 寄存器数量 | CRC校验 |
接收报文格式 | 从站地址 | 功能码 | 字节计数 | 数据 | CRC校验 |
举例:读取输出寄存器——读取2号站点从10开始的4个寄存器
使用串口发送返回的命令。
4)04H功能码读取输入寄存器
发送报文格式 | 从站地址 | 功能码 | 开始寄存器地址 | 寄存器数量 | CRC校验 |
接收报文格式 | 从站地址 | 功能码 | 字节计数 | 数据 | CRC校验 |
举例:读取输入寄存器——读取2号站点从10开始的4个寄存器
主从站进行设置。
然后,设置线圈的数量,及读取的个数位置。
使用串口发送返回的命令。
5)05H功能码预置单线圈
发送报文格式 | 从站地址 | 功能码 | 线圈地址 | 线圈值 | CRC校验 |
接收报文格式 | 从站地址 | 功能码 | 线圈地址 | 线圈值 | CRC校验 |
举例:预置单线圈——将2号站点的05地址置位
主从站进行设置。
然后,设置线圈的数量,及读取的个数位置。
接下来我们发送报文,观察返回值。
6)06H功能码预置单寄存器
发送报文格式 | 从站地址 | 功能码 | 寄存器地址 | 寄存器值 | CRC校验 |
接收报文格式 | 从站地址 | 功能码 | 寄存器地址 | 寄存器值 | CRC校验 |
举例:预置单寄存器——将5号站点10地址写入123
7)0FH功能码预置多线圈
发送报文格式 | 从站地址 | 功能码 | 起始线圈地址 | 数量+字节计数+数据 | CRC校验 |
接收报文格式 | 从站地址 | 功能码 | 起始线圈地址 | 数量 | CRC校验 |
举例:预置多线圈——将1号站点从1开始的5个线圈写入True Flase True Flase
首先,设置线圈。
选择多线圈写入。
8)10H功能码预置多寄存器
发送报文格式 | 从站地址 | 功能码 | 起始寄存器地址 | 数量+字节数+数据 | CRC校验 |
接收报文格式 | 从站地址 | 功能码 | 起始寄存器地址 | 数量 | CRC校验 |
举例:预置多寄存器——将1号站点从10开始的5个寄存器分别写入01 02 03 04 05