Modbus 协议简介
Modbus协议是一种已广泛应用于当今工业控制领域的通用通讯协议。通过此协议,控制器相互之间、或控制器经由网络(如以太网)可以和其它设备之间进行通信。Modbus协议使用的是主从通讯技术,即由主设备主动查询和操作从设备。一般将主控设备方所使用的协议称为Modbus Master,从设备方使用的协议称为Modbus Slave。典型的主设备包括工控机和工业控制器等;典型的从设备如PLC可编程控制器等。Modbus通讯物理接口可以选用串口(包括RS232、RS485和RS422),也可以选择以太网口。
通信方式
1、以太网:对应的通信模式是Modbus TCP/IP
ModbusTCP的数据帧可分为两部分:ADU=MBAP+PDU = MBAP + 功能码 + 数据域,MBAP 7byte,功能码1byte,数据域不确定,由具体功能决定。
MBAP为报文头,长度为7字节,组成如下:
事务处理标识 | 协议标识 | 长度 | 单元标识符 |
2*8bit | 2*8bit | 2*8bit | 8bit |
内容 | 解释 |
---|---|
事务处理标识 | 可以理解为报文的序列号,一般每次通信之后就要加1以区别不同的通信数据报文 |
协议标识符 | 00 00表示ModbusTCP协议 |
长度 | 表示接下来的数据长度,单位为字节 |
单元标识符 | 可以理解为设备地址 |
PDU=功能码+数据域,功能码1byte,数据域不确定。
功能代码 | 数据数量 |
8bit | n |
2、异步串行传输(各种介质如有线RS-232-/422/485/;光纤、无线等):对应的通信模式是Modbus RTU或Modbus ASCII
ASCII模式的数据帧
起始位 | 设备地址 | 功能代码 | 数据数量 | 数据 | LRC高字节 | LRC低字节 | 结束符 |
: | 2*8bit | 2*8bit | n | n*8bit | 8bit | 8bit | CR、LF(回车、换行) |
RTU模式的数据帧
起始位 | 设备地址 | 功能代码 | 数据数量 | 数据 | CRC低字节 | CRC高字节 | 结束符 |
无 | 8bit | 8bit | n | n*8bit | 8bit | 8bit | 无 |
RTU和ASCII的区别
a、RTU模式下,一个字节的数据,传输的就是一个字节。ASCII模式下,同样一个字节数据用了两个字节来传输。例如,要传输数字0x5B,RTU传输的是0101 1011(二进制),而ASCII传输的是00110101和01000010。可见,ASCII传输的速率是RTU的一半。
b、ASCII模式采用LRC校验,RTU模式采用16位CRC校验。
c、ASCII有开始标记和结束标记,RTU没有
Modbus的四种数据类型
输出线圈:大小只有1bit,ON或OFF,可读可写,既可以是一个输出量输出点,也可以是数字量输入点,有效的地址范围是1-9999。
输入离散量:大小只有1bit,ON或OFF,只读,即数字量输出点,有效地址范围是10001-19999。
输入寄存器:16bit的寄存器,只读,可以用作模拟量或16位打包输入点,有效地址范围是30001-39999。
保持寄存器:16bit的寄存器,可读可写,既可以是一个模拟量或16位打包输入点,也可以是模拟量或16位打包输出点,有效地址范围是40001-49999。
在PLC或DCS上用点名标记不同的变量,在Modbus则以数据地址来标记每个点。以上所说的地址都是参考地址,而不是实际的物理地址。上述的地址是在设备中的地址,按照PLC的习惯从1开始递增,而Modbus报文中是从0开始递增。例如地址偏移为4、5、6的Holding Register,其实是指参考地址是40005、40006、40007的寄存器。
常用功能码
功能码 | 名称 | 功能 | 对应的地址类型 |
01 | 读线圈状态 | 读位(读N个bit)---读从机线圈寄存器,位操作 | 0x |
02 | 读输入离散量 | 读位(读N个bit)---读离散输入寄存器,位操作 | 1x |
03 | 读多个寄存器 | 读整型、字符型、状态字、浮点型(读N个words)---读保持寄存器,字节操作 | 4X |
04 | 读输入寄存器 | 读整型、状态字、浮点型(读N个words)---读输入寄存器,字节操作 | 3x |
05 | 写单个线圈 | 写位(写一个bit)---写线圈寄存器,位操作 | 0x |
06 | 写单个保持寄存器 | 写整型、字符型、状态字、浮点型(写一个word)---写保持寄存器,字节操作 | 4x |
0F | 写多个线圈 | 写位(写n个bit)---强置一串连续逻辑线圈的通断 | 0x |
10 | 写多个保持寄存器 | 写整形、字符型、状态字、浮点型(写n个word)---把具体的二进制值装入一串连续的保持寄存器 | 4x |
数据解析
(1)、0x01:读线圈
在从站中读1~2000个连续线圈状态,ON=1,OFF=0
请求:MBAP 功能码 起始地址H 起始地址L 数量H 数量L(共12字节)
响应:MBAP 功能码 数据长度 数据(长度:9+ceil(数量/8)
如:在从站0x01中,读取开始地址为0x0002的线圈数据,读0x0008位----00 01 00 00 00 06 01 01 00 02 00 08
回:数据长度为0x01个字节,数据为0x01,第一个线圈为ON,其余为OFF----00 01 00 00 00 04 01 01 01 01
(2)、0x05:写单个线圈
将从站中的一个输出写成ON或OFF,0xFF00请求输出为ON,0x000请求输出为OFF
请求:MBAP 功能码 输出地址H 输出地址L 输出值H 输出值L(共12字节)
响应:MBAP 功能码 输出地址H 输出地址L 输出值H 输出值L(共12字节)
如:将地址为0x0003的线圈设为ON----00 01 00 00 00 06 01 05 00 03 FF 00
回:写入成功----00 01 00 00 00 06 01 05 00 03 FF 00
(3)、0x0F:写多个线圈
将一个从站中的一个线圈序列的每个线圈都强制为ON或OFF,数据域中置1的位请求相应输出位ON,置0的位请求响应输出为OFF
请求:MBAP 功能码 起始地址H 起始地址L 输出数量H 输出数量L 字节长度 输出值H 输出值L(长度:13+ceil(数量/8)
响应:MBAP 功能码 起始地址H 起始地址L 输出数量H 输出数量L(共12字节)
如:向起始地址为0x0000,数量为0x000A的线圈写入数据,字节长度为0x02,数据为0x1301----00 01 00 00 00 09 01 0F 00 00 00 0A 02 13 01
回:写入成功----00 01 00 00 00 06 01 0F 00 00 00 0A
(4)、0x02:读离散量输入
从一个从站中读1~2000个连续的离散量输入状态
请求:MBAP 功能码 起始地址H 起始地址L 数量H 数量L(共12字节)
响应:MBAP 功能码 数据长度 数据(长度:9+ceil(数量/8)
如:从地址0x0000开始读0x0012个离散量输入----00 01 00 00 00 06 01 02 00 00 00 12
回:数据长度为0x03个字节,数据为0x01 04 00,表示第一个离散量输入和第11个离散量输入为ON,其余为OFF----00 01 00 00 00 06 01 02 03 01 04 00
(5)、0x04:读输入寄存器
从一个远程设备中读1~2000个连续输入寄存器
请求:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12字节)
响应:MBAP 功能码 数据长度 寄存器数据(长度:9+寄存器数量×2)
如:读起始地址为0x0002,数量为0x0005的寄存器数据----00 01 00 00 00 06 01 04 00 02 00 05
回:数据长度为0x0A,第一个寄存器的数据为0x0c,其余为0x00----00 01 00 00 00 0D 01 04 0A 00 0C 00 00 00 00 00 00 00 00
(6)、0x03:读保持寄存器
从远程设备中读保持寄存器连续块的内容
请求:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12字节)
响应:MBAP 功能码 数据长度 寄存器数据(长度:9+寄存器数量×2)
如:起始地址是0x0000,寄存器数量是 0x0003----00 01 00 00 00 06 01 03 00 00 00 03
回:数据长度为0x06,第一个寄存器的数据为0x21,其余为0x00----00 01 00 00 00 09 01 03 06 00 21 00 00 00 00
(7)、0x06:写单个保持寄存器
在一个远程设备中写一个保持寄存器
请求:MBAP 功能码 寄存器地址H 寄存器地址L 寄存器值H 寄存器值L(共12字节)
响应:MBAP 功能码 寄存器地址H 寄存器地址L 寄存器值H 寄存器值L(共12字节)
如:向地址是0x0000的寄存器写入数据0x000A----00 01 00 00 00 06 01 06 00 00 00 0A
回:写入成功----00 01 00 00 00 06 01 06 00 00 00 0A
(8)、0x10:写多个保持寄存器
在一个远程设备中写连续寄存器块(1~123个寄存器)
请求:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L 字节长度 寄存器值(13+寄存器数量×2)
响应:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12字节)
如:向起始地址为0x0000,数量为0x0001的寄存器写入数据,数据长度为0x02,数据为0x000F----00 01 00 00 00 09 01 10 00 00 00 01 02 00 0F
回:写入成功----00 01 00 00 00 06 01 10 00 00 00 01