Modbus协议/ Modbus Protocol
目录
1 Modbus 协议简介
Modbus协议MODICON公司1979年开发的一种通信协议,是一种工业现场总线协议标准,1996年施耐德公司推出了基于以太网TCP/IP的Modbus协议—ModbusTCP。
Modbus协议是一项应用层报文传输协议,包括ASCII / RTU / TCP三种报文类型,协议本身不定义物理层,只定义了控制器能够认识和使用的消息结构,而不管消息是经过何种网络进行通信的。
标准的Modbus协议物理层接口主要有RS232 / RS422 / RS485和以太网。采用Master/Slave主从方式通信。
2 Modbus RTU协议/ Modbus RTU Protocol
Modbus RTU协议报文格式主要如下,
名称 字节数 位号 描述
------------ --------- ------ ------
设备地址 1 1
功能码 1 2 03H读寄存器/06H写单个寄存器/10H写多个寄存器
寄存器地址 2 3-4 高位在前
数据长度 2 5-6 传送数据总长度
CRC校验 2 7-8
下面是不同操作时使用的报文格式
3 Modbus TCP协议/ Modbus TCP Protocol
3.1 Modbus TCP协议格式
Modbus TCP协议报文格式主要可分为两段,MBAP和PDU,
MBAP:
名称 字节数 位号 描述
------------ --------- ------ ------
事物标识符 2 1-2 由服务器复制返回,通常为\x00\x00
协议表示符 2 3-4 通常为\x00\x00
数据长度 2 5-6 传送数据总长度,高位通常\x00(数据不超过256),低位为后续字节长度
单元标识符 1 7 通常为\x00
PDU:
名称 字节数 位号 描述
------------ --------- ------ ------
功能码 1 8 定义功能
起始寄存器 2 9-10 操作的寄存器起始位
寄存器/数据 2 11-12 读/多个写模式下,为寄存器数量,单个写模式为写入数据
3.2 Modbus TCP加解码的 Python 实现/ Modbus TCP Encode and Decode by Python
1 importstruct2
3
4 classModbusCodeC():5 """
6 This CodeC class implement partly of Modbus encode and decode7 The chamber only offer 03H and 06H function-code for using8 """
9
10 @staticmethod11 defMBAP_encode():12 transFlagHi = b'\x00'
13 transFlagLo = b'\x00'
14 protoFlag = b'\x00\x00'
15 length = b'\x00\x06'
16 unitFlag = b'\x00'
17 mbap = transFlagHi + transFlagLo + protoFlag + length +unitFlag18 returnmbap19
20 @staticmethod21 def PDU_encode(func, regi, num=1, data=None):22 funcList = {'r': b'\x03',23 'w': b'\x06'}24 funcCode =funcList[func]25 registerStart = struct.pack('!H', regi)26 registerNum = struct.pack('!H', num)27 if data and func == 'w':28 dataCode = struct.pack('!H', data)29 pdu = funcCode + registerStart +dataCode30 returnpdu31 pdu = funcCode + registerStart +registerNum32 returnpdu33
34 @staticmethod35 def encode(func, regi, num, data=None):36 return ModbusCodeC.MBAP_encode() +ModbusCodeC.PDU_encode(func, regi, num, data)37
38 @staticmethod39 defMBAP_decode(s):40 m ={}41 m['transFlagHi'] = s[:1]42 m['transFlagLo'] = s[1:2]43 m['protoFlag'] = s[2:4]44 m['length'] = s[4:6]45 m['unitFlag'] = s[6:]46 returnm47
48 @staticmethod49 defPDU_decode(s):50 p ={}51 '''
52 p['funcCode'] = s[:1]53 p['registerStart'] = s[1:3]54 p['registerNum'] = s[3:5]55 p['data'] = s[5:]56 '''
57 #TODO: Add bit number and data length check here
58 p['funcCode'] = s[:1]59 p['bitNum'] = s[1:2]60 p['data'] = s[2:]61 returnp62
63 @staticmethod64 defdecode(msg):65 msg_de ={}66 mbap, pdu = msg[:7], msg[7:]67 msg_de['MBAP'] =ModbusCodeC.MBAP_decode(mbap)68 msg_de['PDU'] =ModbusCodeC.PDU_decode(pdu)69 returnmsg_de70
71 if __name__ == '__main__':72 print(ModbusCodeC.encode('r', 5, 3))73 print(ModbusCodeC.encode('w', 5, 1, 8))
4 Modbus功能码/ Modbus Function Code
在Modbus功能码中,1-65位为公共功能码,定义了一些通用的功能
5 Modbus TCP/RTU对比/ Modbus TCP/RTU Comparison
5.1 Modbus RTU与Modbus TCP读指令对比
MBAP报文头
地址码
功能码
寄存器地址
寄存器数量
CRC校验
Modbus RTU
无
01
03
01 8E
00 04
25 DE
Modbus TCP
00 00 00 00 00 06 00
无
03
01 8E
00 04
无
指令的涵义:从地址码为01(TCP协议单元标志为00)的模块0x18E(01 8E)寄存器地址开始读(03)四个(00 04)寄存器。
5.2 Modbus RTU与Modbus TCP写指令对比
MBAP报文头
地址码
功能码
寄存器地址
寄存器数量
数据长度
正文
CRC校验
RTU
无
01
10
01 8E
00 01
02
00 00
A8 7E
TCP
00 00 00 00 00 09 00
无
10
01 8E
00 01
02
00 00
无
指令的涵义:从地址码为01(TCP协议单元标志为00)的模块0x18E(01 8E)寄存器地址开始写(10)一个(00 01)寄存器,具体数据长度为2个字节(02),数据正文内容为00 00(00 00)。
参考链接