STM32
直播中

胖子的逆袭

12年用户 1122经验值
私信 关注
[问答]

Modbus协议是什么


    Modbus协议是什么?


        MODBUS功能码有哪些?

        MODBUS协议有哪几种传输模式?

回帖(1)

乔占宽

2021-9-29 16:28:32
    一、MODBUS简介

    ①Modbus协议是一种请求/应答的串行链路协议,是一种工业现场总线协议标准。是一项应用层报文传输协议,用于在通过不同类型的总线或网络连接的设备之间的客户机/服务器通信。
    ②Modbus协议是一项应用层报文传输协议,包括ASCII、RTU、TCP三种报文类型。
    ③标准的Modbus协议物理层接口有RS232、RS422、RS485和以太网接口,采用master/slave方式通信。
    ④MODBUS 是一项应用层报文传输协议,用于在通过不同类型的总线或网络连接的设备之间的客户机/服务器通信。
    MODBUS 通用帧如图:




       二、MODBUS功能码详解

    1. 寄存器分类

    Modbus寄存器分为四种,如表
    [tr]寄存器种类数据类型访问类型功能码PLC地址寄存器地址[/tr]
    线圈寄存器读写01H 05H 0FH00001-099990000H-FFFFH
    离散输入寄存器只写02H10001-199990000H-FFFFH
    输入寄存器只写04H30001-399990000H-FFFFH
    保持寄存器读写03H 06H 10H40001-499990000H-FFFFH
    2. 常用功能码

    Modbus中常用功能码有8个,可以分为位操作和字操作两类,如表所示:
    [tr]功能码描述PLC地址寄存器地址位/字操作操作数量[/tr]
    01H读线圈寄存器00001-099990000H-FFFFH位操作单个或多个
    02H读离散输入寄存器10001-199990000H-FFFFH位操作单个或多个
    03H读保持寄存器40001-499990000H-FFFFH字操作单个或多个
    04H读输入寄存器30001-399990000H-FFFFH字操作单个或多个
    05H写单个线圈寄存器00001-099990000H-FFFFH位操作单个
    06H写单个保持寄存器40001-499990000H-FFFFH字操作单个
    0FH写多个线圈寄存器00001-099990000H-FFFFH位操作多个
    10H写多个保持寄存器40001-499990000H-FFFFH字操作多个
    2. 常用功能码说明

    ①读线圈寄存器——01H

    ●功能码01H读取Modbus从机中线圈寄存器的状态,可以是单个寄存器,或者多个连续的寄存器。
    ●假设从机地址为01H,读取的线圈寄存器的起始地址为0017H,读取38个寄存器,指令如表所示:
    发送读线圈寄存器指令:
    [tr]从机地址功能码起始地址高位起始地址低位寄存器数量高位寄存器数量低位CRC高位CRC低位[/tr]
    0101001700260DD4
    ●响应:各线圈的状态与数据内容的每个bit对应,1代表ON,0代表OFF。如果查询的线圈数量不是8的倍数,则在最后一个字节的高位补0。
    读线圈寄存器状态响应:
    [tr]从机地址功能码返回字节数数据1数据2数据3数据4数据5CRC高位CRC低位[/tr]
    010105CD6BB20E1B44EA
    ●其中,第一个字节CDH对应线圈0017H到001E的状态,转为二进制是11001101,其中bit0对应0017H,bit7对应001E,如表所示:
    线圈0017H到001EH的状态:
    [tr]001EH001DH001CH001BH001AH0019H0018H0017H[/tr]
    ONONOFFOFFONONOFFON
    ●最后一个字节为1BH,对应线圈0037H到003CH的状态,转为二进制是00011011,其中bit0对应0037H,bit5对应003CH,其余两位用0填充,如表所示:
    线圈0037H到003CH的状态:
    [tr]001EH001DH001CH001BH001AH0019H0018H0017H[/tr]
    ONONOFFOFFONONOFFON
    ②读离散输入寄存器——02H

    ●功能码02H读取Modbus从机中离散输入寄存器的状态,可以是单个寄存器,或者多个连续的寄存器。
    ●假设从机地址为01H,读取的离散输入寄存器的起始地址为00C4H,读取22个寄存器,指令如表所示:
    发送读离散输入寄存器指令:
    [tr]从机地址功能码起始地址高位起始地址低位寄存器数量高位寄存器数量低位CRC高位CRC低位[/tr]
    010200C40016B839
    ●响应:各个离散输入寄存器的状态与数据内容的每个bit对应,1代表ON,0代表OFF。如果查询的线圈数量不是8的倍数,则在最后一个字节的高位补0
    读离散输入寄存器的返回结果:
    [tr]从机地址功能码返回字节数数据1数据2数据3CRC高位CRC低位[/tr]
    010203ACDB352288
    ●其中,第一个字节ACH对应00C4H到00CBH寄存器的状态,转为二进制是10101100,其中bit0对应00C4H,bit7对应00CB,如表所示:
    寄存器00C4H到00CBH的状态:
    [tr]00CBH00CAH00C9H00C8H00C7H00C6H00C5H00C4H[/tr]
    10101100
    ONOFFONOFFONONOFFOFF
    ●最后一个字节为35H,对应寄存器00D4H到00D9H的状态,转为二进制是00110101,其中bit0对应00D4H,bit5对应00D9H,其余两位用0填充,如表所示:
    寄存器00D4H到00D9H的状态
    [tr]00DBH00DAH00D9H00D8H00D7H00D6H00D5H00D4H[/tr]
    00110101
    ONOFFONOFFONONOFFOFF
    ③读保持寄存器——03H

    ●功能码03H读取Modbus从机中保持寄存器的数据,可以是单个寄存器,或者多个连续的寄存器。
    ●假设从机地址为01H,读取的保持寄存器的起始地址为006BH,读取3个寄存器,指令如表所示:
    发送读保持寄存器指令:
    [tr]从机地址功能码起始地址高位起始地址低位寄存器数量高位寄存器数量低位CRC高位CRC低位[/tr]
    0103006B00037417
    ●响应:每个保持寄存器的长度为2个字节。保持寄存器之间,低地址寄存器先传输,高地址寄存器后传输。单个保持寄存器,高字节数据先传输,低字节数据后传输。
    读保持寄存器的返回结果:
    [tr]从机地址功能码字节数006BH高位字节006BH低位字节006CH高位字节006CH低位字节006BH高位字节006BH低位字节CRC高位CRC低位[/tr]
    010306006B00130000F579
    ④读输入寄存器——04H

    ●功能码04H读取Modbus从机中输入寄存器的数据,可以是单个寄存器,或者多个连续的寄存器。
    ●假设从机地址为01H,读取的保持寄存器的起始地址为0008H,读取2个寄存器,指令如表所示:
    发送读输入寄存器指令:
    [tr]从机地址功能码起始地址高位起始地址低位寄存器数量高位寄存器数量低位CRC高位CRC低位[/tr]
    0104006B00020017
    ●响应:每个输入寄存器的长度为2个字节。输入寄存器之间,低地址寄存器先传输,高地址寄存器后传输。单个输入寄存器,高字节数据先传输,低字节数据后传输。
    读输入寄存器的返回结果:
    [tr]从机地址功能码字节数0008H高位字节0008H低位字节0009H高位字节0009H低位字节CRC高位CRC低位[/tr]
    010404000A000B9A41
    ⑤写单个线圈寄存器——05H

    ●功能码05H写单个线圈寄存器,FF00H请求线圈处于ON状态,0000H请求线圈处于OFF状态。
    ●假设从机地址为01H,线圈寄存器的地址为00ACH,使其处于ON状态的指令,如表所示:
    发送写单个线圈指令:
    [tr]从机地址功能码起始地址高位起始地址低位寄存器数量高位寄存器数量低位CRC高位CRC低位[/tr]
    010500ACFF004C1B
    ●响应:如果写入成功,返回发送的指令,即010500ACFF004C1B。
    [tr]从机地址功能码起始地址高位起始地址低位寄存器数量高位寄存器数量低位CRC高位CRC低位[/tr]
    010500ACFF004C1B
    ⑥写单个保持寄存器——06H

    ●功能码06H写单个保持寄存器。
    ●假设从机地址为01H,保持寄存器的地址为0001H,数据位0003H,指令如表所示:
    发送写单个保持寄存器指令:
    [tr]从机地址功能码起始地址高位起始地址低位寄存器数量高位寄存器数量低位CRC高位CRC低位[/tr]
    010600010003980B
    ●响应:如果写入成功,返回发送的指令,即010600010003980B。
    [tr]从机地址功能码起始地址高位起始地址低位寄存器数量高位寄存器数量低位CRC高位CRC低位[/tr]
    010600010003980B
    ⑦写多个线圈寄存器——0FH

    ●功能码0FH写多个线圈寄存器。如果对应的数据位为1,表示线圈状态为ON;如果对应的数据位为0,表示线圈状态为OFF。线圈寄存器之间,低地址寄存器先传输,高地址寄存器后传输。单个线圈寄存器,高字节数据先传输,低字节数据后传输。如果写入的线圈寄存器的个数不是8的倍数,则在最后一个字节的高位补0。
    ●假设从机地址为01H,线圈寄存器的起始地址为0013H,写入10个寄存器,指令如表所示:
    发送写入多个线圈寄存器指令:
    [tr]从机地址功能码起始地址高位起始地址低位寄存器数量高位寄存器数量低位字节数数据1数据2CRC高位CRC低位[/tr]
    010F0013000A02CD0172CB
    ●其中,CDH对应线圈0013H到001AH的内容,01H对应线圈001B到001CH的内容,未使用位用0填充。
    线圈寄存器0013H到001CH的内容:
    [tr]001AH0019H0018H0017H0016H0015H0014H0013H[/tr]
    11001101
    [tr]0022H0021H0020H001FH001EH001DH001CH001BH[/tr]
    00000001
    ●响应:如果写入成功,返回写入的寄存器数量,如表所示
    写多个线圈寄存器的返回结果:
    [tr]从机地址功能码起始地址高位起始地址低位寄存器数量高位寄存器数量低位CRC高位CRC低位[/tr]
    010F0013000A2409
    ⑧写多个保持寄存器——10H

    ●功能码10H写多个保持寄存器,其中每个保持寄存器的长度为两个字节。
    ●假设从机地址为01H,保持寄存器的起始地址为0001H,写入2个寄存器,指令如表所示:
    发送写入多个保持寄存器指令:
    [tr]从机地址功能码起始地址高位起始地址低位寄存器数量高位寄存器数量低位字节数0001H高位0001H低位0002H高位0002H低位CRC高位CRC低位[/tr]
    010100001000204000A01029230
    ●响应:如果写入成功,返回写入的寄存器数量,如表所示:
    [tr]从机地址功能码起始地址高位起始地址低位寄存器数量高位寄存器数量低位CRC高位CRC低位[/tr]
    0110000100021008
    3.小结

    ●功能码详解主要参考文献为:

      三、MODBUS协议详解

    1.两种串行传输模式

    ①.ASCII模式

      编码系统:
    十六进制,ASCII 字符 0-9, A-F。报文中每个 ASCII 字符含有 1 个十六进制字符
    Bits per Byte:
    1 起始位
    7 数据位, 首先发送最低有效位
    1 位作为奇偶校验
    1 停止位
    奇偶校验 :
    ●偶校验是要求的, 其它模式 ( 奇校验, 无校验 ) 也可以使用。 为了保证与其它产品的最大兼容性,同时支持无校验模式是建议的。默认校验模式模式 必须为偶校验。
    注 : 使用无校验要求 2 个停止位。
    字符串行传送:
    ●每个字符或字节均由此顺序发送(从左到右):
    ●最低有效位 (LSB) . . . 最高有效位 (MSB),数据传输如图:
    ●有奇偶检验





    ●无奇偶检验:






    Modbus ASCII 报文帧:
    在 ASCII 模式, 报文用特殊的字符区分帧起始和帧结束。一个报文必须以一个‘冒号’ ( : )(ASCII 十六进制 3A )起始,以 ‘回车-换行’ (CR LF) 对 (ASCII 十六进制 0D 和 0A) 结束。
    注 : LF 字符可以通过特定的 Modbus 应用命令 (参见 Modbus 应用协议规范) 改变。
    对于所有的域,允许传送的字符为十六进制 0–9, A–F (ASCII 编码)。 设备连续的监视总线上的 ‘冒号’ 字符。 当收到这个字符后,每个设备解码后续的字符一直到帧结束。
    报文帧包括:起始、地址、功能码、数据、LRC校验位、结束。如图:





    注:每个字符子节需要用两个字符编码。因此,为了确保 ASCII 模式 和 RTU 模式在 Modbus 应用级兼容,ASCII
    数据域最大数据长度为 (2x252) 是 RTU 数据域 (252) 的两倍。
    必然的, Modbus ASCII 帧的最大尺寸为 513 个字符。
    ASCII 传输模式状态如图:





    帧检验域:
    ①帧检验方式为::纵向冗余校验 (LRC - Longitudinal Redundancy Checking)

    ②LRC 域检验不包括起始“冒号”和结尾 CRLF 对的整个报文的内容。不管报文有无奇偶校验,均执行此检验。

    ③LRC 域为一个子节,包含一个 8 位二进制值。LRC 值由发送设备计算,然后将 LRC 附在报文后面。接收设备在接收报文时重新计算 LRC 的值,并将计算结果于实际接收到的 LRC 值相比较。如果两个值不相等,则为错误。LRC 的计算, 对报文中的所有的连续 8 位字节相加,忽略任何进位,然后求出其二进制补码。执行检验针对不包括起始“冒号”和结尾 CRLF 对的整个 ASCII 报文域的内容。在 ASCII 模式,LRC 的结果被 ASCII 编码为两个字节并放置于 ASCII 模式报文帧的结尾, CRLF 之前。
      ②.RTU模式

    RTU模式:报文中每个 8 位字节含有两个 4 位十六进制字符。这种模式的主要优点是较高的数据密度,在相同的波特率下比ASCII 模式有更高的吞吐率。每个报文必须以连续的字符流传送。
    编码系统:
    8–位二进制报文中每个 8 位字节含有两个 4 位十六进制字符(0–9, A–F)
    Bits per Byte:
    1 起始位
    8 数据位, 首先发送最低有效位
    1 位作为奇偶校验
    1 停止位
    奇偶校验 :
    ●偶校验是要求的, 其它模式 ( 奇校验, 无校验 ) 也可以使用。 为了保证与其它产品的最大兼容性,同时支持无校验模式是建议的。默认校验模式模式 必须为偶校验。
    注 : 使用无校验要求 2 个停止位。
    字符串行传送:
    ●每个字符或字节均由此顺序发送(从左到右):
    ●最低有效位 (LSB) . . . 最高有效位 (MSB),数据传输如图:
    ●有奇偶校验:





    ●无奇偶校验:






    Modbus RTU 报文帧:
    RTU 报文帧描述如图 :





    注意: Modbus RTU 帧最大为 256 字节。
    ●在 RTU 模式,报文帧由时长至少为 3.5 个字符时间的空闲间隔区分。在后续的部分,这个时间区间被称作 t3.5。如果两个字符之间的空闲间隔大于 1.5 个字符时间,则报文帧被认为不完整应该被接收节点丢弃。传输格式如图:










    注 :
    RTU 接收驱动程序的实现,由于 t1.5 和 t3.5 的定时,隐含着大量的对中断的管理。在高通信速率下,这导致 CPU 负担加重。因此,在通信速率等于或低于 19200 Bps 时,这两个定时必须严格遵守;对于波特率大于 19200 Bps 的情形,应该使用 2 个定时的固定值:建议的字符间超时时间(t1.5)为 750µs,帧间的超时时间 (t1.5) 为 1.750ms。

    ●下图表示了对 RTU 传输模式状态图的描述。 “主节点” 和 “子节点” 的不同角度均在相同的图中表示:





    上面状态图的一些解释:
    ● 从 “初始” 态到 “空闲” 态转换需要 t3.5 定时超时: 这保证帧间延迟
    ● “空闲” 态是没有发送和接收报文要处理的正常状态。
    ●在 RTU 模式, 当没有活动的传输的时间间隔达 3.5 个字符长时,通信链路被认为在 “空闲”
    态。
    ●当链路空闲时, 在链路上检测到的任何传输的字符被识别为帧起始。 链路变为 “活动” 状态。
    然后, 当链路上没有字符传输的时间间个达到 t3.5 后,被识别为帧结束。
    ● 检测到帧结束后,完成 CRC 计算和检验。然后,分析地址域以确定帧是否发往此设备,如果不是,则丢弃此帧。 为了减少接收处理时间,地址域可以在一接到就分析,而不需要等到整个帧结束。这样,CRC 计算只需要在帧寻址到该节点 (包括广播帧) 时进行。
    帧检验域:
    ①帧检验方式为:循环冗余校验 (CRC)

    ②CRC 包含由两个 8 位字节组成的一个 16 位值。

    ③CRC 域作为报文的最后的域附加在报文之后。计算后,首先附加低字节,然后是高字节。CRC

    ④高字节为报文发送的最后一个子节。附加在报文后面的 CRC 的值由发送设备计算。接收设备在接收报文时重新计算 CRC 的值,
    并将计算结果于实际接收到的 CRC 值相比较。如果两个值不相等,则为错误。CRC 的计算, 开始对一个 16 位寄存器预装全 1。 然后将报文中的连续的 8 位子节对其进行后续的计算。只有字符中的 8 个数据位参与生成 CRC 的运算,起始位,停止位和校验位不参与 CRC计算。

    ⑤CRC 的生成过程中, 每个 8–位字符与寄存器中的值异或。然后结果向最低有效位(LSB)方向移动(Shift) 1 位,而最高有效位(MSB)位置充零。 然后提取并检查 LSB:如果 LSB 为 1, 则寄存器中的值与一个固定的预置值异或;如果 LSB 为 0, 则不进行异或操作。
    这个过程将重复直到执行完 8 次移位。完成最后一次(第 8 次)移位及相关操作后,下一个 8位字节与寄存器的当前值异或,然后又同上面描述过的一样重复 8 次。当所有报文中子节都运算之后得到的寄存器忠的最终值,就是 CRC。
      ③小结

      MODBUS分为两种传输模式,ASCII方式、RTU方式。这两种模式的区别在于:  1、起始符,与结束符不一样; ●ASCII模式,起始符是一个冒号“:” ASCII码为3AH H是十六进制表示结束符是“回车换行符” ASCII码为0DH 0AH
    ●RTU 模式,起始符与结束符都是至少3.5倍字符传输时间的停顿间隔时间标定3.5倍字符的传输时间的计算方法,根据“通讯格式、传输方式及MODBUS协议简介”视频中介绍的一个字符的传输时间的计算方法,很容易计算出来。
    2、校验和计算不一样;
    ●ASCII模式,是LRC校验
    ●RTU 模式,是CRC校验
    3、发送格式不一样;
    ●ASCII模式,在消息中的每个字节都作为两个ASCII字符发送
    ●RTU 模式,在消息中的每个字节包含两个 4Bit的十六进制字符。
      2. ModbusTCP

    ●ModbusTCP的数据帧可分为两部分:MBAP+PDU。

    ①结构帧MBAP

    MBAP为报文头,长度为7字节,组成如下:
    [tr]事务紧急处理标识协议标识长度单元标识符[/tr]
    2字节2字节2字节1字节
    事务处理标识 : 可以理解为报文的序列号,一般每次通信之后就要加1以区别不同的通信数据报文。
    协议标识符 : 00 00表示ModbusTCP协议。
    长度 : 表示接下来的数据长度,单位为字节。
    单元标识符 : 可以理解为设备地址。
    ②结构帧PDU

    PDU由功能码+数据组成。功能码为1字节,数据长度不定,由具体功能决定。该处使用的url网络请求的数据。
    ②小结

      modbus设备可分为主站(poll)和从站(slave)。主站只有一个,从站有多个,主站向各从站发送请求帧,从站给予响应。在使用TCP通信时,主站为client端,主动建立连接;从站为server端,等待连接。

    ●主站请求:功能码+数据
    ●从站正常响应:请求功能码+响应数据
    ●从站异常响应:异常功能码+异常码,其中异常功能码即将请求功能码的最高有效位置1,异常码指示差错类型
    ●注意:需要超时管理机制,避免无期限的等待可能不出现的应答
      在linux下使用modbusTCP连接
    IANA(Internet Assigned Numbers Authority,互联网编号分配管理机构)给Modbus协议赋予TCP端口号为502,这是目前在仪表与自动化行业中唯一分配到的端口号。
    通信过程
    1.connect 建立TCP连接
    2.准备modbus报文
    3.使用send命令发送报文
    4.在同一连接下等待应答
    5.使用recv命令读取报文,完成一次数据交换
    6.通信任务结束时,关闭TCP连接
      四、基于STM32-MODBUS实现

    1.硬件介绍

    ①主板 “司南电气控制STM32单片机开发板”,如图





    ②485串口线
    ③电脑需要安装 MODBUS上位机软件,通过485串口线与司南电气控制STM32单片机开发板的485的通讯接口连接。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分