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


    Modbus协议 / Modbus Protocol


    目录

    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         由服务器复制返回,通常为x00x00

    协议表示符   2      3-4         通常为x00x00

    数据长度       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'x00x00'
    15         length = b'x00x06'
    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 RTUModbus 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 RTUModbus 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

  • 相关阅读:
    mysql常用命令
    怎么在cmd中输入mysql就可以进去mysql控制台
    ORA-01659: 无法分配超出 7 的 MINEXTENTS
    Oracle修改表空间自增长
    整理下.net分布式系统架构的思路
    Net分布式系统之一:系统整体框架介绍
    QT QTreeWidget 的一个例子 显示文件(夹)的树形结构
    待读 QT 博客
    如何为 QT5 装上 QT4 才有的库
    Python 获取文件夹里所有 log 的起止时间戳
  • 原文地址:https://www.cnblogs.com/stacklike/p/8149941.html
Copyright © 2020-2023  润新知