输入banner图图片脚本导航/分类

Python的网络编程[6] -> Modbus 协议 -> Modbus 的基本理论与 Python 实现


目录

  1. Modbus 协议简介
  2. Modbus RTU协议
  3. Modbus TCP协议与 Python 实现
  4. Modbus 功能码
  5. Modbus TCP/RTU对比

 

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 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

 

Python的网络编程[6] -> Modbus 协议 -> Modbus 的基本理论与 Python 实现

标签:基于   控制   ber   使用   开始   定义   参考   def   pdu