Modbus協議 / Modbus Protocol
目錄
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 import struct 2 3 4 class ModbusCodeC(): 5 """ 6 This CodeC class implement partly of Modbus encode and decode 7 The chamber only offer 03H and 06H function-code for using 8 """ 9 10 @staticmethod 11 def MBAP_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 + unitFlag 18 return mbap 19 20 @staticmethod 21 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 + dataCode 30 return pdu 31 pdu = funcCode + registerStart + registerNum 32 return pdu 33 34 @staticmethod 35 def encode(func, regi, num, data=None): 36 return ModbusCodeC.MBAP_encode() + ModbusCodeC.PDU_encode(func, regi, num, data) 37 38 @staticmethod 39 def MBAP_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 return m 47 48 @staticmethod 49 def PDU_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 return p 62 63 @staticmethod 64 def decode(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 return msg_de 70 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)。
參考鏈接
http://blog.csdn.net/yangbingzhou/article/details/39504015
http://www.485-can-tcp.com/technology/232485/Modbus.htm