modbus_modbus通讯协议 - CSDN
modbus 订阅
Modbus是一种串行通信协议,是Modicon公司(现在的施耐德电气 Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus已经成为工业领域通信协议的业界标准(De facto),并且现在是工业电子设备之间常用的连接方式。 展开全文
Modbus是一种串行通信协议,是Modicon公司(现在的施耐德电气 Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus已经成为工业领域通信协议的业界标准(De facto),并且现在是工业电子设备之间常用的连接方式。
信息
连接组成
带智能终端通过公用线路连接
定    义
一个工业通信系统
发明时间
1979年
中文名
Modbus通讯协议
外文名
Modbus protocol
Modbus通讯协议简介
Modbus是一种串行通信协议,是Modicon公司(现在的施耐德电气Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus已经成为工业领域通信协议的业界标准(De facto),并且现在是工业电子设备之间常用的连接方式。 [1]  Modbus比其他通信协议使用的更广泛的主要原因有: [2]  Modbus允许多个 (大约240个) 设备连接在同一个网络上进行通信,举个例子,一个由测量温度和湿度的装置,并且将结果发送给计算机。在数据采集与监视控制系统(SCADA)中,Modbus通常用来连接监控计算机和远程终端控制系统(RTU)。
收起全文
精华内容
参与话题
  • Modbus协议讲解及实现

    千人学习 2020-03-31 10:55:20
    本课程主讲老师集10多年在Modbus协议学习、使用中的经验心得,结合当前物联网浪潮下Modbus协议开发的痛点,推出这套面向Modbus 协议初学者的课程。本课程不同于以往市面课程只是协议讲解无实现代码,而是采用讲解与...
  • Modbus 通讯协议 (RTU传输模式)

    万次阅读 多人点赞 2020-09-28 16:31:53
    第一章Modbus协议简介 Modbus协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。它已经成为一通用工业标准。有了它,不同厂商生产的控制...

    注:( 2020.05.22 )

    GB/T 19582.2-2008 《基于Modbus协议的工业自动化网络规范 第1部分:Modbus协议在串行链路上的实现指南》

     

    1、对于modbus ASCII 模式,使用的是高位字节在前,低位字节在后。使用LRC校验。

     

    2、对于modbus rtu 模式,使用的是低位字节在前,高位字节在后。使用CRC校验。

     

     

     

     

    第一章          Modbus协议简介

     

    Modbus协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。它已经成为一通用工业标准。有了它,不同厂商生产的控制设备可以连成工业网络,进行集中监控。

    此协议定义了一个控制器能认识使用的消息结构,而不管它们是经过何种网络进行通信的。它描述了一控制器请求访问其它设备的过程,如果回应来自其它设备的请求,以及怎样侦测错误并记录。它制定了消息域格局和内容的公共格式。

    当在一Modbus网络上通信时,此协议决定了每个控制器须要知道它们的设备地址,识别按地址发来的消息,决定要产生何种行动。如果需要回应,控制器将生成反馈信息并用Modbus协议发出。在其它网络上,包含了Modbus协议的消息转换为在此网络上使用的帧或包结构。这种转换也扩展了根据具体的网络解决节地址、路由路径及错误检测的方法。

    协议在一根通讯线上使用应答式连接(半双工),这意味着在一根单独的通讯线上信号沿着相反的两个方向传输。首先,主计算机的信号寻址到一台唯一的终端设备(从机),然后,在相反的方向上终端设备发出的应答信号传输给主机。 协议只允许在主计算机和终端设备之间,而不允许独立的设备之间的数据交换,这就不会在使它们初始化时占据通讯线路,而仅限于响应到达本机的查询信号。

     

    1. 1  传输方式

    传输方式是一个信息帧内一系列独立的数据结构以及用于传输数据的有限规则,以RTU模式在Modbus总线上进行通讯时,信息中的每8位字节分成2个4位16进制的字符,每个信息必须连续传输下面定义了与Modebus 协议– RTU方式相兼容的传输方式。

    代码系统

    ·   8位二进制,十六进制数0...9,A...F

    ·   消息中的每个8位域都是一个两个十六进制字符组成

    每个字节的位

    ·   1个起始位

    ·   8个数据位,最小的有效位先发送

    ·   1个奇偶校验位,无校验则无

    ·   1个停止位(有校验时),2个Bit(无校验时)

    错误检测域

    ·   CRC(循环冗长检测)

    1.2      协议

    信息帧到达终端设备时,它通过一个简单的“口”进入寻址到的设备,该设备去掉数据帧的“信封”(数据头),读取数据,如果没有错误,就执行数据所请求的任务,然后,它将自己生成的数据加入到取得的“信封”中,把数据帧返回给发送者。返回的响应数据中包含了以下内容:终端从机地址(Address)、被执行了的命令(Function)、执行命令生成的被请求数据(Data)和一个校验码(Check)。发生任何错误都不会有成功的响应。

    1.2.1          信息帧

    Address

    Function

    Data

    Check

    8-Bits

    8-Bits

    N x 8-Bits

    16-Bits

    图 1 – 1 . 信息帧格式

    特注:Modbus信息帧所允许的最大长度为256个字节,即N的范围是大于等于零且小于等于252(N{0,252})。

    即,所有的数据一共256个,数据剩下253个。

    1.2.2          地址(Address)域

    信息帧地址域(信息地址)在帧的开始部分,由8位组成,有效的从机设备地址范围0-247(十进制),各从机设备的寻址范围为1-247。主机把从机地址放入信息帧的地址区,并向从机寻址。从机响应时,把自己的地址放入响应信息的地址区,让主机识别已作出响应的从机地址。

    地址0广播地址,所有从机均能识别。当Modbus协议用于高级网络时,则不允许广播或其它方式替代。

    1.2.3          功能(Function)域

      信息帧功能域代码告诉了被寻址到的终端执行何种功能。有效码范围1-225(十进制) ,有些代码是适用于所有控制器,有些适应于某种控制器,还有些保留以备后用。有关功能代替码的全部内容见附录A

    当主机向从句发送信息时,功能代码向从机说明应执行的动作。如读一组离散式线圈或输入信号的ON/OFF状态,读一组寄存器的数据,读从机的诊断状态,写线圈(或寄存器),允许下截、记录、确认从机内的程序等。当从机响应主机时,功能代码可说明从机正常响应或出现错误(即不正常响应),正常响应时,从句简单返回原始功能代码;不正常响应时,从机返回与原始代码相等效的一个码,并把最高有效位设定为“1”。

    如,主机要求从机读一组保持寄存器时,则发送信息的功能码为:

    0000 0011 (十六进制03)

    若从机正确接收请求的动作信息后,则返回相同的代码值作为正常响应。发现错时,则返回一个不正常响信息:

    1000 0011(十六进制83)

    从机对功能代码作为了修改,此外,还把一个特殊码放入响应信息的数据区中,告诉主机出现的错误类型和不正常响应的原因,不正常响应见附录B。主机设备的应用程序负责处理不正常响应,典型处理过程是主机把对信息的测试和诊断送给从机,并通知操作者。表 1 – 1列出了所有设备常用的功能码、它们的意义及它们的初始功能。

    表 1 – 1 常用功能码

    代码

    名称

    作用

    01

    读取线圈状态

    取得一组逻辑线圈的当前状态(ON/OFF)

    02

    读取输入状态

    取得一组开关输入的当前状态(ON/OFF)

    03

    读取保持寄存器

    在一个或多个保持寄存器中取得当前的二进制值

    04

    读取输入寄存器

    在一个或多个输入寄存器中取得当前的二进制值

    05

    强置单线圈

    强置一个逻辑线圈的通断状态

    06

    预置单寄存器

    放置一个特定的二进制值到一个单寄存器中

    07

    读取异常状态

    取得8个内部线圈的通断状态

    15

    强置多线圈

    强置一串连续逻辑线圈的通断

    16

    预置多寄存器

    放置一系列特定的二进制值到一系列多寄存器中

    17

    报告从机标识

    可使主机判断编址从机的类型及该从机运行指示灯的状态

    1.2.4          数据域

    数据域包含了终端执行特定功能所需要的数据或者终端响应查询时采集到的数据。这些数据的内容可能是数值、参考地址或者极限值。他由数据区有2个16进制的数据位(2的8次方256),数据范围为00-FF(16进制)。例如:功能域码告诉终端读取一个寄存器数据域则需要指明从哪个寄存器开始及读取多少个数据,内嵌的地址和数据依照类型和从机之间的不同能力而有所不同。若无错误出现,从机向主机的响应信息中包含了请求数据,若有错误出现,则数据中有一个不正常代码,使主机能判断并作出下一步的动作。数据区的长度可为“零”以表示某类信息。

    1.2.5          错误校验域

    该域允许主机和终端检查传输过程中的错误。有时,由于电噪声和其它干扰,一组数据在从一个设备传输到另一个设备时在线路上可能会发生一些改变,出错校验能够保证主机或者终端不去响应那些传输过程中发生了改变的数据,这就提高了系统的安全性和效率,出错校验使用了16位循环冗余的方法,即CRC校验。

    错误检测域包含一16Bits值(用两个8位的字符来实现)。错误检测域的内容是通过对消息内容进行循环冗长检测方法得出的。CRC域附加在消息的最后,添加时先是低字节然后是高字节。故CRC的高位字节是发送消息的最后一个字节。

    1.2.6          字符的连续传输

    当消息在标准的Modbus系列网络传输时,每个字符或字节按由左到右的次序方式发送:

    最低有效位(LSB)...最高有效位(MSB)。

    位的序列是:

    有奇偶校验

    启始位

    1

    2

    3

    4

    5

    6

    7

    8

    奇偶位

    停止位

    无奇偶校验

    启始位

    1

    2

    3

    4

    5

    6

    7

    8

    停止位

    停止位

    图 1 –2 .  位顺序(RTU)

    1.3   错误检测

    1、奇偶校验

    用户可以配置控制器是奇或偶校验,或无校验。这将决定了每个字符中的奇偶校验位是如何设置的。

    如果指定了奇或偶校验,“1”的位数将算到每个字符的位数中(ASCII模式7个数据位,RTU中8个数据位)。例如RTU字符帧中包含以下8个数据位:1 1 0 0 0 1 0 1

    整个“1”的数目是4个。如果便用了偶校验,帧的奇偶校验位将是0,便得整个“1”的个数仍是4个。如果便用了奇校验,帧的奇偶校验位将是1,便得整个“1”的个数是5个。

    如果没有指定奇偶校验位,传输时就没有校验位,也不进行校验检测。代替一附加的停止位填充至要传输的字符帧中。

    2、CRC检测

    RTU方式时,采用CRC方法计算错误校验码,CRC校验传送的全部数据。它忽略信息中单个字符数据的奇偶校验方法。

    循环冗余校验(CRC)域占用两个字节,包含了一个16位的二进制值。CRC值由传送设备计算出来,然后附加到数据帧上,接收设备在接收数据时重新计算CRC值,然后与接收到的CRC域中的值进行比较,如果这两个值不相等,就发生了错误。

    CRC开始时先把寄存器的16位全部置成“1”,然后把相邻2个8位字节的数据放入当前寄存器中,只有每个字符的8位数据用作产生CRC,起始位,停止位和奇偶校验位不加到CRC中。

           在生成CRC时,每个8位字节与寄存器中的内容进行异或,然后将结果向低位移位,高位则用“0”补充,最低位(LSB)移出并检测,如果是1,该寄存器就与一个预设的固定值进行一次异或运算,如果最低位为0,不作任何处理。

           上述处理重复进行,知道执行完了8次移位操作,当最后一位(第8位)移完以后,下一个8位字节与寄存器材的当前值进行异或运算,同样进行上述的另一个8次移位异或操作,当数据帧中的所有字节都作了处理,生成的最终值就是CRC值。

    生成一个CRC的流程为:

    1、       预置一个16位寄存器为0FFFFH(全1),称之为CRC寄存器。

    2、       把数据帧中的第一个8位字节与CRC寄存器中的低字节进行异或运算,结果存回CRC寄存器。

    3、       将CRC寄存器向右移一位,最高位填以0,最低位移出并检测。

    4、       如果最低位为0:重复第3步(下一次移位)。

     如果最低位为1:将CRC寄存器与一个预设的固定值(0A001H)进行异或运算。

    5、       重复第3步和第4步直到8次移位。这样处理完了一个完整的八位。

    6、       重复第2步到第5步来处理下一个八位,直到所有的字节处理结束。

    7、       最终CRC寄存器得值就是CRC的值。

    CRC值附加到信息时,低位在先,高位在后。查阅附录C中的一个实例,它详细说明了CRC的校验。

    第二章  Modbus数据和控制功能详解

           Modbus信息中的所有数据地址以零作为基准,各项数据的第一个数据地址的编号为0。若无特殊说明在此节文中用+进制值表示,图中的数据区则用十六进制表示

    图2--1为一个例子,说明了Modbus的查询信息,图2--2为正常响应的例子,这两例子中的数据均是16进制的,也表示了以RTU方式构成数据帧的方法。

    主机查询是读保持寄存器,被请求的从机地址是06,读取的数据来自地址40108保持寄有器。注意,该信息规定了寄存器的起始地址为0107 (006BH)。

    从机响应返回该功能代码,说明是正常响应,字节数“Byle count”中说明有多少个8位字节被返回。它表明了附在数据区中8位字节的数量,当在缓冲区组织响应信息时,“字节数”区域中的值应与该信息中数据区的字节数相等。如RTU方式时,63H 用一个字节(01100011)发送。8个位为一个单位计算“字节数”,它忽略了信息帧用组成的方法。

     

    Addr

    Fun

    Data start reg hi

    Data start reg lo

    Data #of regs hi

    Data #of regs lo

    CRC16

    hi

    CRC16

    lo

    06H

    03H

    00H

    6BH

    00H

    01H

    XXH

    XXH

    图 2 – 1 Modbus的查询信息

    Addr

    Fun

    Byte

    count

    Data1

    hi

    Data1

    Lo

    Data 2

    hi

    Data2

    lo

    Data3

    hi

    Data3

    lo

    CRC16

    hi

    CRC16

    lo

    06H

    03H

    06H

    02H

    2BH

    00H

    00H

    00H

    63H

    XXH

    XXH

    图 2 – 2 Modbus的响应信息

    2.1  读取线圈状态(功能码01)

    读取从机离散量输出口(DO,0X类型)的 ON/OFF 状态,不支持广播。

    查询   

    查询信息规定了要读的起始线圈和线圈量,线圈的起始地址为0000H,1-16个线圈的寻址地址分为0000H –0015H(DO1=0000H,DO2=0001H,依此类推)。

           图 2 – 3 的例子是从地址为17的从机读取DO1至DO6的状态。

    Addr

    Fun

    DO start reg hi

    DO start reg lo

    DO #of regs hi

    DO #of regs lo

    CRC16

    hi

    CRC16

    lo

    11H

    01H

    00H

    00H

    00H

    06H

    XXH

    XXH

    图 2 – 3 读取线圈状态----查询

            响应

      响应信息中的各线圈的状态与数据区的每一位的值相对应,即每个DO占用一位(1 = ON, 0= OFF),第一个数据字节的LSB为查询中的寻址地址,其他的线圈按顺序在该字节中由低位向高位排列,直至8个为止,下一个字节也是从低位向高位排例。若返回的线圈数不是8的倍数,则在最后的数据字节中的剩余位至字节的最高位全部填0,字节数区说明全部数据的字节数。

    图2 – 4所示为线圈的输出状态响应的实例。

    Addr

    Fun

    Byte count

    Data

    CRC16  hi

    CRC16  lo

    11H

    01H

    01H

    2AH

    XXH

    XXH

           

         数据

    0

    0

    0

    0

    0

    0

    DO2

    DO1

    MSB

    7

    6

    5

    4

    3

    2

    LSB

    图 2 – 4读取线圈状态----响应

    2.2  读取输入状态(功能码02)

    读取从机离散量输入信号(DI,0X类型)的ON/OFF状态,不支持广播。

    查询

    查询信息规定了要读的输入起始地址,以及输入信号的数量。输入的起始地址为0000H,1-16个输入口的地址分别为0-15(DO1=0000H,DO2=0001H,依此类推)。

    图 2 – 5 的例子是从地址为17的从机读取DI1到DI16的状态。

     

    Addr

    Fun

    DI start

    addr  hi

    DI start

    addr  lo

    DI num

    hi

    DI num

    lo

    CRC16

    hi

    CRC16

    lo

    11H

    02H

    00H

    00H

    00H

    10H

    XXH

    XXH

    图 2 – 5读取输入状态----查询

    响应

           响应信息中的各输入口的状态,分别对应于数据区中的每一位值,1 = ON; 0 = OFF,第一个数据字节的LSB为查询中的寻址地址,其他输入口按顺序在该字节中由低位向高位排列,直至8个位为止。下一个字节中的8个输入位也是从低位到高位排列。若返回的输入位数不是8的倍数,则在最后的数据字节中的剩余位直至字节的最高位全部填零。字节数区说明了全部数据的字节数。

    图2 – 6 所示为读数字输出状态响应的实例。

    Addr

    Fun

    Byte count

    Data1

    Data2

    CRC16 hi

    CRC16 lo

    11H

    02H

    02H

    33H

    CCH

    XXH

    XXH

    数据 1

     DI8

     DI7

     DI6

     DI5

     DI4

     DI3

     DI2

     DI1

           MSB                                       LSB  

    数据 2

     DI16

     DI15

     DI14

     DI13

     DI12

     DI11

     DI10

     DI9

        MSB                                             LSB  

    图 2 – 6读取输入状态----响应

    2.3  读取保持寄存器(功能码03)

    读取从机保持寄存器(4X类型)的二进制数据,不支持广播。

    查询

    查询信息规定了要读的保持寄存器起始地址及保持寄存器的数量,保持寄存器寻址起始地址为0000H,寄存器1-16所对应的地址分别为0000H –0015H。

    图2 – 7 的例子是从17号从机读3个采集到的基本数据U1、U2、U3,U1的地址为0000H, U2的地址为0001H,U3的地址为0002H。

    Addr

    Fun

    Data start

    addr  hi

    Data start

    addr lo

    Data #of

    regs hi

    Data #of

    regs lo

    CRC16

    hi

    CRC16

    lo

    11H

    03H

    00H

    00H

    00H

    03H

    XXH

    XXH

    图 2 – 7读取保持寄存器----查询

    响应

    响应信息中的寄存器数据为二进制数据,每个寄存器分别对应2个字节,第一个字节为高位值数据,第二个字节为低位数据。

    图 2 – 8的例子是读取U1,U2,U3(U1=03E8H,U2=03E7H,U3=03E9H)的响应。

    Addr

    Fun

    Byte

    count

    Data1

    hi

    Data1

    Lo

    Data 2

    hi

    Data2

    lo

    Data3

    hi

    Data3

    lo

    CRC16

    hi

    CRC16

    lo

    11H

    03H

    06H

    03H

    E8H

    03H

    E7H

    03H

    E9H

    XXH

    XXH

    图 2 – 8读取保持寄存器----响应

    2.4   读取输入寄存器(功能码04)

    读取从机输入寄存器(3X类型)中的二进制数据,不支持广播。

    查询

    查询信息规定了要读的寄存器的起始地址及寄存器的数量,寻止起始地址为0,寄存器1-16所对应的地址分别为0000H –0015H。

    图 2 – 9的例子是请求17号从机的0009寄存器。

    Addr

    Fun

    DO addr

    hi

    DO addr

    lo

    Data #of

    regs hi

    Data #of

    regs lo

    CRC16

    hi

    CRC16

    lo

    11H

    04H

    00H

    08H

    00H

    01H

    XXH

    XXH

    图 2 – 9读取输入寄存器----查询

    响应

    响应信息中的寄存器数据为每个寄存器分别对应2个字节,第一个字节为高位数据,第二个字节为低位数据。

    图 2 – 10的例子寄存器30009中的数据用000AH 2个字节表示。

    Addr

    Fun

    Byte

    count

    Data

    hi

    Data

    Lo

    CRC16

    hi

    CRC16

    lo

    11H

    04H

    02H

    00H

    0AH

    XXH

    XXH

    图 2 – 10读取输入寄存器----响应

    2.5   强置单线圈(功能码05)

    强制单个线圈(DO,0X类型)为ON或OFF状态,广播时,该功能可强制所有从机中同一类型的线圈均为ON或OFF状态。

    该功能可越过控制器内存的保护状态和线圈的禁止状态。线圈强制状态一直保持有效直至下一个控制逻辑作用于线圈为止。控制逻辑中无线圈程序时,则线圈处于强制状态。

    查询

    查询信息规定了需要强制一个单独线圈的类型,线圈的起始地址为0000H,1-16个线圈的寻址地址分为0000H –0015H(DO1=0000H,DO2=0001H,依此类推)。

    由查询数据区中的一个常量,规定被请求线圈的ON/OFF状态, FF00H值请求线圈处于ON状态,0000H值请求线圈处于OFF状态,其它值对线圈无效,不起作用。

    图示 2-11的例子是请求17号从机开DO1的On状态。

     

    Addr

    Fun

    DO addr

    hi

    DO addr

    lo

    Value

    hi

    Value

    lo

    CRC16

    hi

    CRC16

    lo

    11H

    05H

    00H

    00H

    FFH

    00H

    XXH

    XXH

    图示 2-11强制单线圈----查询

    响应

    图2 – 12所示为对这个命令请求的正常响应是在DO状态改变以后传送接收到的数据。

     

    Addr

    Fun

    DO addr

    hi

    DO addr

    lo

    Value

    hi

    Value

    lo

    CRC16

    hi

    CRC16

    lo

    11H

    05H

    00H

    00H

    FFH

    00H

    XXH

    XXH

    图示 2-12强制单线圈----响应

    2.6 预置单寄存器(功能码06)

    把一个值预置到一个保持寄存器(4X类型)中,广播时,该功能把值预置到所有从机的相同类型的寄存器中

    该功能可越过控制器的内存保护。使寄存器中的预置值保持有效。只能由控制器的下一个逻辑信号来处理该预置值。若控制逻辑中无寄存器程序时,则寄存器中的值保持不变。

    查询

           查询信息规定了要预置寄存器的类型,寄存器寻址起始地址为0000H,寄存器1所对应的地址为0000H。

           图示 2-13的例子是请求17号从机0040H.的值为2717。

    Addr

    Fun

    Data start

    reg  hi

    Data start

       reg lo

    Value

      hi

    Value    

      lo

    CRC

      hi

    CRC

      lo

     11H

    06H

       00H

       40H

      0AH

     9DH

     XXH

     XXH

    图示 2-13预设单寄存器----查询

    响应

    图2 – 14所示对于预置单寄存器请求的正常响应是在寄存器值改变以后将接收到的数据传送回去。

    Addr

    Fun

    Data start

    reg  hi

    Data start

       reg lo

    Value

      hi

    Value    

      lo

    CRC

      hi

    CRC

      lo

     11H

    06H

       00H

       40H

      0AH

     9DH

     XXH

     XXH

    图示 2-14预设单寄存器----响应

    2.7读取异常状态(功能码7)

    读从中机中8个不正常状态线圈的数据,某些线圈号已在不同型号的控制器中预定义,而其它的线圈由用户编程,作为有关控制器的状态信息,如“machine ON/OFF”,“heads retraced”,(缩回标题),“safeties satisfied”(安全性满意),“errorconditions”(存在错误条件)或其它用户定义的标志等。该功能码不支持广播。

    该功能代码为存取该类信息提供了一种简单的方法,不正常线圈的类型是已知的(在功能代码中不需要线圈类型) 预定义的不正常线圈号如下:

    控制器型号                 线圈                 设定

    M84,184/384,584,984           1-8                    用户定义

    484                          257                  电池状态

                                              258-264             用户定义

             884                          761                   电池状态

                                              762                   内存保护状态

                                              763                   R10工况状态

                                       764-768         用户预定义

    查询     

           图示 2-15的例子是请求读从机设备17中的不正常状态。

    Addr

    Fun

    CRC16  hi

    CRC16  lo

    11H

    07H

    XXH

    XXH

    图示 2-15读取异常状态----查询

    响应

    正常响应包含 8 个不正常的线圈状态,为一个数据字节,每个线圈一位。LSB对应为最低线圈类型的状态。

    图2 – 16所示按查询要求返回响应:

    Addr

    Fun

    DO Data

    CRC16  hi

    CRC16  lo

    11H

    07H

    6DH

    XXH

    XXH

    图示 2-16读取异常状态----响应

    该例子中,线圈数据为 6DH (二进制0110 ,1101),从左到右 (最高位至最低位) 的线圈状态分别为: OFF – ON – ON – OFF – ON –ON – OFF – ON。若控制器型号为 984,这些位表示线圈 8 至 1 的状态;若控制器型号为 484 则表示线圈 264 至 257 的状态。

    2.8 强置多线圈(功能码15)

    按线圈的顺序把各线圈 (DO,0X 类型) 强制成 ON 或 OFF。广播时,该功能代码可对各从机中相同类型的线圈起强制作用。

    该功能代码可越过内存保护和线圈的禁止状态线圈。保持强制状态有效,并只能由控制器的下一个逻辑来处理。若无线圈控制逻辑程序时,线圈将保持强制状态。

    查询

    查询信息规定了被强制线圈的类型,线圈的起始地址为0000H,1-16个线圈的寻址地址分为0000H –0015H(DO1=0000H,DO2=0001H,依此类推)。

    查询数据区规定了被请求线圈的 ON/OFF 状态,如数据区的某位值为“1”表示请求的相应线圈状态为ON,位值为“0”,则为OFF状态。

    图示 2-17例子为请求从机设备 17 中一组 10 个线圈为强制状态,起始线圈为 20 (则寻址地址为 19 或 13H),查询的数据为 2 个字节,CD01H (二进制 11001101 0000 0001) 相应线圈的二进制位排列如下:

    Bit:

    1

    1

    0

    0

    1

    1

    0

    1

    0

    0

    0

    0

    0

    0

    0

    1

    Coll:

    27

    26

    25

    24

    23

    22

    21

    20

    -

    -

    -

    -

    -

    -

    29

    28

    传送的第一个字节 CDH 对应线圈为 27-20,  LSB 对应线圈 20,传送的第二个字节为 01H,对应的线圈为 29-28, LSB 为继圈 28,其余未使用的位均填“0”。

    Addr

    Fun

    DO addr

    hi

    DO addr

    lo

    Data #of

     reg  hi

    Data #of

     reg lo

    Byte   

    count      

    Value

      hi

    Value

     lo

    CRC

      hi

    CRC

      lo

     11H

    0FH

       00H

       13H

       00H

       0AH

      02H

     CDH

     01H

     XXH

     XXH

    图示 2-17强置多线圈----查询

    响应

    正常响应返回从机地址,功能代码,起始地址以及强制线圈数。

    图2 – 18对上述查询返回的响应。

    Addr

    Fun

    DO addr

    hi

    DO addr

    lo

    Data #of

    reg  hi

    Data #of

    reg lo

    CRC16

    hi

    CRC16

    lo

    11H

    0FH

    00H

    13H

    00H

    0AH

    XXH

    XXH

    图示 2-18强置多线圈----响应

    2.9预置多寄存器(功能码16)

    把数据按顺序预置到各 (4X类型) 寄存器中,广播时该功能代码可把数据预置到全部从机中的相同类型的寄存器中。

    该功能代码可越过控制器的内存保护,在寄存器中的预置值一直保持有效,只能由控制器的下一个逻辑来处理寄存器的内容,控制逻辑中无该寄存器程序时,则寄存器中的值保持不变。

    查询

           查询信息规定了要预置寄存器的类型,寄存器寻址起始地址为0000H,寄存器1所对应的地址为0000H。

           图示 2-19的例子是请求17号从机0040H.的值为178077833。

    Addr

    Fun

    Data start

    reg  hi

    Data start

       reg lo

    Data #of

     reg  hi

    Data #of

     reg lo

    Byte   

    count      

    Value

      hi

    Value

     lo

    Value

      hi

    Value    

      lo

    CRC

      hi

    CRC

      lo

     11H

    10H

       00H

       40H

       00H

       02H

      04H

     40H

     89H

      0AH

     9DH

     XXH

     XXH

    图示 2-19预设多寄存器----查询

    响应

    图2 – 20所示对于预置单寄存器请求的正常响应是在寄存器值改变以后将接收到的数据传送回去。

    Addr

    Fun

    Data start

    reg  hi

    Data start

    reg lo

    Data #of

    reg  hi

    Data #of

    reg lo

    CRC16

    hi

    CRC16

    lo

    11H

    10H

    00H

    40H

    00H

    02H

    XXH

    XXH

    图示 2-20预设多寄存器----响应

    2.10报告从机标识(功能码17)

    返回一个从机地址控制器的类型,从机的当前状态,以及有关从机的其他说明,不支持广播。

    查询

                  图示 2-21的例子是请求报告从机设备 17 的 标识ID 和状态。

    Addr

    Fun

    CRC16  hi

    CRC16  lo

    11H

    11H

    XXH

    XXH

    图示 2-21报告从机标识----查询

    响应

    图2 – 22所示正常响应格式,数据内容对应每台控制器的类型。

    Addr

    Fun

    Byte

    Count

    Slave ID

    Run Indicator Status

    Additfional

    Data

    CRC16

    hi

    CRC16

    lo

    11H

    11H

    XXH

    XXH

    XXH

    XXH

    XXH

    XXH

    图示 2-22报告从机标识----响应

    从机 ID 总结

    数据区第一个字节为 Modicon 控制器返回的从机 ID

    Slave ID               Controller

    0                                                    Micro 84

    1                                                    484

    2                                                    184/384

    3                                                    584

    8                    884

    9                    984

    特注:详细信息见Modbus协议英文版或中文版。

    第三章  附录

    附录A:MODBUS全部功能码

    ModBus网络是一个工业通信系统,由带智能终端的可编程序控制器和计算机通过公用线路或局部专用线路连接而成。其系统结构既包括硬件、亦包括软件。它可应用于各种数据采集和过程监控。下表3--1是ModBus的功能码定义。

    表3--1 ModBus功能码

    功能码

    名称

    作用

    01

    读取线圈状态

    取得一组逻辑线圈的当前状态(ON/OFF)

    02

    读取输入状态

    取得一组开关输入的当前状态(ON/OFF)

    03

    读取保持寄存器

    在一个或多个保持寄存器中取得当前的二进制值

    04

    读取输入寄存器

    在一个或多个输入寄存器中取得当前的二进制值

    05

    强置单线圈

    强置一个逻辑线圈的通断状态

    06

    预置单寄存器

    把具体二进值装入一个保持寄存器

    07

    读取异常状态

    取得8个内部线圈的通断状态,这8个线圈的地址由控制器决定,用户逻辑可以将这些线圈定义,以说明从机状态,短报文适宜于迅速读取状态

    08

    回送诊断校验

    把诊断校验报文送从机,以对通信处理进行评鉴

    09

    编程(只用于484)

    使主机模拟编程器作用,修改PC从机逻辑

    10

    控询(只用于484)

    可使主机与一台正在执行长程序任务从机通信,探询该从机是否已完成其操作任务,仅在含有功能码9的报文发送后,本功能码才发送

    11

    读取事件计数

    可使主机发出单询问,并随即判定操作是否成功,尤其是该命令或其他应答产生通信错误时

    12

    读取通信事件记录

    可是主机检索每台从机的ModBus事务处理通信事件记录。如果某项事务处理完成,记录会给出有关错误

    13

    编程(184/384 484 584)

    可使主机模拟编程器功能修改PC从机逻辑

    14

    探询(184/384 484 584)

    可使主机与正在执行任务的从机通信,定期控询该从机是否已完成其程序操作,仅在含有功能13的报文发送后,本功能码才得发送

    15

    强置多线圈

    强置一串连续逻辑线圈的通断

    16

    预置多寄存器

    把具体的二进制值装入一串连续的保持寄存器

    17

    报告从机标识

    可使主机判断编址从机的类型及该从机运行指示灯的状态

    18

    (884和MICRO 84)

    可使主机模拟编程功能,修改PC状态逻辑

    19

    重置通信链路

    发生非可修改错误后,是从机复位于已知状态,可重置顺序字节

    20

    读取通用参数(584L)

    显示扩展存储器文件中的数据信息

    21

    写入通用参数(584L)

    把通用参数写入扩展存储文件,或修改之

    22~64

    保留作扩展功能备用

     

    65~72

    保留以备用户功能所用

    留作用户功能的扩展编码

    73~119

    非法功能

     

    120~127

    保留

    留作内部作用

    128~255

    保留

    用于异常应答

    ModBus网络只是一个主机,所有通信都由他发出。网络可支持247个之多的远程从属控制器,但实际所支持的从机数要由所用通信设备决定。采用这个系统,各PC可以和中心主机交换信息而不影响各PC执行本身的控制任务。表3--2是ModBus各功能码对应的数据类型。

    表3--2 ModBus功能码与数据类型对应表

    代码

    功能

    数据类型

    01

    02

    03

    整型、字符型、状态字、浮点型

    04

    整型、状态字、浮点型

    05

    06

    整型、字符型、状态字、浮点型

    08

    N/A

    重复“回路反馈”信息

    15

    16

    整型、字符型、状态字、浮点型

    17

    字符型

    附录B:不正常响应

    不正常响应:

    除广播外,主机向从机设备发送查询并希望有一个正常响应,主机查询中有可能产生4种事件:

    ¨  从机接收查询,通讯错误正常处理信息,则返回一个正常响应事件。

    ¨  由于通讯出错,从机不能接收查询数据,因而不返回响应。此时,主机依靠处理程序给出查询超时事件。

    ¨  若从机接收查询,发现有 (LRC或CRC) 通讯错误,并返回响应,此时,依靠主机处理程序给出查询超时事件。

    ¨  从机接收查询,无通讯错误,但无法处理(如读不存在的线圈和寄存器)时,向主机报告错误的性质。

    不正常响应信息有2个与正常响应不相同的区域:

    功能代码区:正常响应时,从机的响应功能代码区,带原查询的功能代码。所有功能代码的MSB为0(其值低于80H)。不正常响应时,从机把功能代码的MSB置为1,使功能代码值大于80H,高于正常响应的值。这样,主机应用程序能识别不正常响应事件,能检查不正常代码的数据区。

    数据区:正常响应中,数据区含有(按查询要求给出的) 数据或统计值,在不正常响应中,数据区为一个不正常代码,它说明从机产生不正常响应的条件和原因。

    例:主机发出查询,从机不正常响应。(为十六进制数据)。

    查询:

    Addr

    Fun

    DO start reg hi

    DO start reg lo

    DO #of regs hi

    DO #of regs lo

    CRC16

    Hi

    CRC16

    Lo

    0AH

    01H

    04H

    A1H

    00H

    01H

    XXH

    XXH

    响应(不正常或例外):

    Addr

    Fun

    Exception Code

    CRC16

    Hi

    CRC16

    Lo

    0AH

    81H

    02H

    XXH

    XXH

    图 3 – 1 . 不正常信息帧格式

    上例中,从机设备地址10(0AH),读线圈状态的功能代码(01),主机请求线圈状态的地址为1245(04A1H)。注意:只读一个指定线圈,地址为(0001).

    若从机中不存在此线圈地址时,即以不正常代码(02),向主机返回一个不正常响应。说明为不合法地址。

    表3--3 ModBus的不正常代码:

    代码

    名称

    含义

    01

    不合法功能代码

    从机接收的是一种不能执行功能代码。发出查询命令后,该代码指示无程序功能。

    02

    不合法数据地址

    接收的数据地址,是从机不允许的地址。

    03

    不合法数据

    查询数据区的值是从机不允许的值。

    04

    从机设备故障

    从机执行主机请求的动作时出现不可恢复的错误。

    05

    确认

    从机已接收请求处理数据,但需要较长的处理时间,为避免主机出现超时错误而发送该确认响应。主机以此再发送一个“查询程序完成”未决定从机是否已完成处理。

    06

    从机设备忙碌

    从机正忙于处理一个长时程序命令,请求主机在从机空闲时发送信息。

    07

    否定

    从机不能执行查询要求的程序功能时,该代码使用十进制13或14代码,向主机返回一个“不成功的编程请求”信息。主机应请求诊断从机的错误信息。

    08

    内存奇偶校验错误

    从机读扩展内存中的数据时,发现有奇偶校验错误,主机按从机的要求重新发送数据请求。

    ///

    功能码

    描述

    是否支持广播

    起始地址

    备注

    01

    读线圈状态DO

    不支持

    0000H

    离散量输出口(0X类型)状态

    02

    读输入位状态DI

    不支持

    0000H

    离散量输入信号(0X类型)状态

    03

    读保持寄存器

    不支持

    0000H

    保持寄存器数据

    04

    读输入寄存器

    不支持

    0000H

    输入寄存器(3X类型)数据

    05

    强制单个线圈DO

    支持

    0000H

    强制单个线圈(0X类型)状态

    06

    预置单个保持寄存器

    支持

    0000H

    保持寄存器(4X类型)

    07

    读不正常状态

    不支持

     

     

    08

    诊断(见第3章)

     

    不支持

    0000H

     

    09

    程序 484

    0000H

    没查到

    10

    查询 484

    0000H

    没查到

    11

    通讯事件控制

    不支持

     

     

    12

    通讯事件记录

    不支持

     

     

    13

    程序控制器

    0000H

    没查到

    14

    查询控制器

    0000H

    没查到

    15

    强制多个线圈DO

    支持

    0000H

    强制各线圈 (0X 类型)状态

    16

    预置多个保持寄存器

    支持

    0000H

    保持寄存器(4X类型)

    17

    报告从机 ID

    不支持

     

     

    18

    程序 884/M84

    0000H

    没查到

    19

    通讯链路复位

    0000H

    没查到

    20

    读通用参考值

    不支持

    0000H

    扩展寄存器(6X类型)

    21

    写通用参考值

    不支持

    0000H

    扩展寄存器(6X类型)

    22

    掩码写入4X类型寄存器

    不支持

    0000H

    保持寄存器(4X类型)

    23

    读/写4X类型寄存器

    不支持

    0000H

    保持寄存器(4X类型)

    24

    读FIFO查询数据

    不支持

    0000H

    保持寄存器(4X类型)

     

    展开全文
  • MODBUS通讯详解(博客园)

    千次阅读 2019-01-29 11:01:37
    MODBUS是一个工业上通信常用的通讯协议,一般在PLC上面用的比较多,主要是定义了一种数据传输的规范,比如数据发给谁,数据是干嘛的,数据错没错,接收到数据的从机告诉我数据有没有接受到等.  传输的方式的话比较多的是...

           MODBUS是一个工业上通信常用的通讯协议,一般在PLC上面用的比较多,主要是定义了一种数据传输的规范,比如数据发给谁,数据是干嘛的,数据错没错,接收到数据的从机告诉我数据有没有接受到等.

          传输的方式的话比较多的是使用RS232c形式的串口传输,当然485传输也可以,比较高端的可以使用网络的tcp传输,但是是和之前的串口传输有区别的。

          在使用232传输的时候,整个系统中只有一个主机,剩下的全部是设备,也就是说,只有作为主机的那个角色才能初始化网络,并且对整个网络上的所有从机进行控制,从机和从机之间不允许直接通讯,这就相当于一台PLC对它外接的设备进行控制了。

          在使用TCP传输的时候就没有主机从机的概念了,对等技术通讯,也就是说,所有的节点的地位是对等的,控制器即可以接受数据并作出响应,也可以主动查询网络上另一个控制器的状态,当然,但是协议上,依然会有主机从机的数据定义。

      之所以这样是因为在232的网络上没有冲突检测,要是两个主机,那数据很容易就混乱了,但是到了tcp时代,底层的数据链路层已经做了冲突检测的工作,自然就可以同时传输不担心数据撞车了.

      到这里我们看看modbus数据传输的协议模型

      开头是地址帧,在modbus网络中,每一个从机都有一个地址,主机在访问从机的时候依靠这个唯一的地址识别,多个从机接收到主机的数据的时候,匹配接收到的数据和自身的地址,匹配上的那个从机作出响应,其他的都忽略。

      第二个是功能码,决定这一帧数据主要是干嘛的,输入数据,输出数据,读取控制量等。

      第三是数据,可以有也可以没有。

      第四是差错校验,用来对之前发送的数据校验,防止发送过程中因为电磁干扰,数据出错。

     

          上面只是简单地协议原型,接下来这个协议原型有两种实现,分别叫做ascii实现和RTU实现,我个人比较喜欢称之为命令行实现和代码实现,为什么这么叫后面你就会知道了.首先我们要知道,modbus是按byte传输的,也就是一次传输一个字节

    RTU模式

      在该模式下,传输是这样的

           首先,数据以帧为单位传输,如果一byte数据的传输时间为T,那么每两帧之间的间隔最小应该要大于3.5T,否则从机不能分辨这是两帧,第二,同一帧连续的两个数据之间的间隔时间不能超过1.5T,否则节点会认为这一帧数据不完整,这说明我们在modbus传输的时候要使能一个定时器的工作.

          其次,地址位一个字节,功能代码一个字节,数据n字节,crc校验2字节,那么这个n的限制是多少?协议规定一帧中数据最多是252字节,最少可以是0字节。

     

      Ascii模式

    在该模式下,传输的帧中的数据的每一位只能是ascii码的0-9、a-f,因为RTU模式下一字节一个数据,也就是1字节0x00-0xff,所以在ascii模式下为了传送相同的数据,必须两个字节标识一个有效数据,也就是如下

            可以看到,在Ascii模式下,不是依靠时间间隔判定帧起始了,而是依靠特定字符判断,结束也是按照特定字符判断,起始的判断是’:’字符,结束的判断是windows下的回车换行,数据的最大长度被扩容到了2*252,这样,两种传输模式能传输相同的数据量,但是ascii传输的更慢了。

           但是并不是说时间判据在ascii模式中就没有用了,还是有用的,字符间的间隔不能大于1s,大于1s认为这一帧数据丢失.同样我们可以计算出来ascii帧的最大长度是513字节。

           这个时候你能理解为什么这个叫命令行模式了,因为这种模式下发送的是可视化的字符串,可以人工的输入,而之前的RTU模式,手工输入多麻烦啊,一般程序输入,而且我们可以判定,他以回车换行作为结尾,应该早期主要是在windows上调试的,因为linux只需要回车就能实现windows的回车换行,在这种模式下可以把指令写在文本中直接输入.不过这两年acsii模式用的少了,因为调试软件的出现简化了手工输入的步骤.

      说到这里,两种模式之间的不同还有一个校验方式的不同,RTU使用CRC校验ASCII使用LRC校验

    首先看看CRC

    然后是LRC

      前面说了,不符合时间规则的数据将会被丢掉,那主机怎么知道被丢掉了呢?而且假如主机向100设备发数据,网络里面没有100怎么办?

      是这样的,modbus最多能支持255个子设备的接入,地址从0x01-0xff,而0x00是广播地址,也就是说,0x00发送的数据所有的设备都要接收,但是不能响应,而其他的节点的设备在收到数据之后,必须在有限的时间里面进行响应,或者说是应答,主机端会有一个超时管理,超过一定时间没有反应就会认为数据丢失,该时间可以自由设置,设计者在设计的时候应当保证尽量使得超时时间大于任何一个外设的响应时间.

      其实,当设备接收到了数据应该怎么应答,这个时候又分为正确应答和错误应答,正确应答很好说,还是这个格式的数据帧

      地址是从机自己的地址,功能码和主机发送来的功能码保持一致,数据看需求(功能码的需求)

             错误的请求的回应,还是在功能码上下功夫,之前忘了说,功能码是从0x00-0x7f,也就是最高位都是0,当请求出错的时候,将主机发送过来的功能码加上一个0x80,让最高位为1就OK了,数据部分可以定义一个异常码,比如请求获取温度,发现温度传感器离线了,定义一个异常码0x01,数据域放0x01,主机就知道出错的具体原因是什么了.

      到这里基本上写一部分就说完了,最后附录上modbus预定义的功能码和异常码,具体可以参考modbus协议文档.

    功能码有:

     

    异常码为

     

    展开全文
  • Modbus学习总结

    万次阅读 多人点赞 2020-04-23 23:55:37
    一、介绍Modbus 协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。Modbus协议定义了一个控制器能认识使用的消息结构,而不管它们是经过何...

    一、介绍

    Modbus 协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。Modbus协议定义了一个控制器能认识使用的消息结构,而不管它们是经过何种网络进行通信的。它描述了一控制器请求访问其它设备的过程,如果回应来自其它设备的请求,以及怎样侦测错误并记录。它制定了消息域格局和内容的公共格式。

    Modbus 是一个请求/应答协议。也叫做SlaveMasterServerClient
    同一种设备在不同领域的不同叫法。
    Slave工业自动化用语;响应请求;
    Master:工业自动化用语;发送请求;
    ServerIT用语;响应请求;
    ClientIT用语;发送请求;
    Modbus中,SlaveServer意思相同,MasterClient意思相同。

     

    modbus结构示意图

    二、协议分类

    ModBus协议是应用层报文传输协议(OSI模型第7层),它定义了一个与通信层无关的协议数据单元(PDU),即PDU=功能码+数据域。     

    ModBus协议能够应用在不同类型的总线或网络。对应不同的总线或网络,Modbus协议引入一些附加域映射成应用数据单元(ADU),即ADU=附加域+PDU。目前,

    Modbus有下列三种通信方式: 

     1.以太网,对应的通信模式是MODBUS TCP。 

     2.异步串行传输(各种介质如有线RS-232-/422/485/;光纤、无线等),对应的通信模式是MODBUS RTU或MODBUS ASCII。     

     3.高速令牌传递网络,对应的通信模式是Modbus PLUS。

     

    ASCII模式

    :

    地址

    功能代码

    数据数量

    数据1

    ...

    数据n

    LRC高4位字节值

    LRC低4位字节值

    回车

    换行

    RTU模式

    地址

    功能代码

    数据数量

    数据1

    ...

    数据n

    CRC高字节

    CRC低字节

     所选的ASCII或RTU方式仅适用于标准的Modbus网络,它定义了在这些网络上连续传输的消息段的每一位,以及决定怎样将信息打包成消息域和如何解码。“数据数量”字段只有在响应包中才有。

     

    三、Modbus消息帧

    两种传输模式中(ASCII或RTU),传输设备以将Modbus消息转为有起点和终点的帧,这就允许接收的设备在消息起始处开始工作,读地址分配信息,判断哪一个设备被选中(广播方式则传给所有设备),判知何时信息已完成。部分的消息也能侦测到并且错误能设置为返回结果。

    1、ASCII帧

     使用ASCII模式,消息以冒号(:)字符(ASCII码 3AH)开始,以回车换行符结束(ASCII码 0DH,0AH)。

     其它域可以使用的传输字符是十六进制的0...9,A...F。网络上的设备不断侦测“:”字符,当有一个冒号接收到时,每个设备都解码下个域(地址域)来判断是否发给自己的。

     

     消息中字符间发送的时间间隔最长不能超过1秒,否则接收的设备将认为传输错误。一个典型消息帧如下所示:

    起始位

    设备地址

    功能代码

    数据

    LRC校验

    结束符

    1个字符

    2个字符

    2个字符

    n个字符

    2个字符

    2个字符

    2、RTU帧

     使用RTU模式,消息发送至少要以3.5个字符时间的停顿间隔开始。在网络波特率下多样的字符时间,这是最容易实现的(如下图的T1-T2-T3-T4所示)。传输的第一个域是设备地址。可以使用的传输字符是十六进制的0...9,A...F。网络设备不断侦测网络总线,包括停顿间隔时间内。当第一个域(地址域)接收到,每个设备都进行解码以判断是否发往自己的。在最后一个传输字符之后,一个至少3.5个字符时间的停顿标定了消息的结束。一个新的消息可在此停顿后开始。

     

     整个消息帧必须作为一连续的流转输。如果在帧完成之前有超过1.5个字符时间的停顿时间,接收设备将刷新不完整的消息并假定下一字节是一个新消息的地址域。同样地,如果一个新消息在小于3.5个字符时间内接着前个消息开始,接收的设备将认为它是前一消息的延续。这将导致一个错误,因为在最后的CRC域的值不可能是正确的。一典型的消息帧如下所示:

    起始位

    设备地址

    功能代码

    数据

    CRC校验

    结束符

    T1-T2-T3-T4

    8Bit

    8Bit

    n个8Bit

    16Bit

    T1-T2-T3-T4

     

    消息帧的地址域包含两个字符(ASCII)或8Bit(RTU)。可能的从设备地址是0...247 (十进制)。单个设备的地址范围是1...247。主设备通过将要联络的从设备的地址放入消息中的地址域来选通从设备。当从设备发送回应消息时,它把自己的地址放入回应的地址域中,以便主设备知道是哪一个设备作出回应。地址0是用作广播地址,以使所有的从设备都能认识。当Modbus协议用于更高水准的网络,广播可能不允许或以其它方式代替。

    应答包中,数据包括了数据字节长度+数据值,请求包中数据只包含数据值。

     Modbus TCP/IP数据帧结构

    Modbus TCP/IP数据帧除了TCP已经有的包头外,还有modbus TCP协议数据单元(ADU),包括MBAP帧头以及与RTU数据内容相同的应用数据单元(PDU),地址码除外。

           其中与单纯的TCP/IP或是modbus-RTU相比,多的内容就是一个MBAP报文头:

    MBAP报文头定义

           可以看出来,MBAP报文头主要添加了以下附加信息,为了识别是请求还是响应而设置的事务元标识符(2个字节,通常为0,客户端发出的检验信息,服务器端只是需要将这两个字节的内容复制以后再放到回复报文的相应位置就可以)、为了判断协议类型设置的协议标识符(2个字节,0=MODBUS协议)、为了区分可变长度数据帧结束的数据帧长度(从下一个字节起至结束的长度,2个字节)、还有用于标识从站地址的单元标识符(1个字节,即从站地址),与RTU不同的是,从站地址放在了MBAP帧头里。这个里面的2个字节默认都是大端对齐(高字节、低字节)。

    PDU单元与MODBUS RTU数据内容基本相同,由于有TCP/IP和链路层(以太网)校验和机制所以去掉了CRC校验码,从站地址也放在了MBAP帧头里。

    另外Modbus TCP/IP默认端口为502 

    例子:

    Modbus 控制命令为:
    00 01 00 00 00 09 04     10 00 00 00 01 02 00 01

           MBAP                                PDU

    上述命令可简单的解释为:00 01(事务标识符)00 00(协议标识符)00 09(后续字节数)04(设备标识符,即从站地址)10(功能码,写多个保持寄存器值)00 00(第一个地址,即地址 100 01(写寄存器的个数,1个)02(后续所写数据的长度)00 01(具体写的数据)。

     

    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)寄存器。

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

    MODBUS ASCII和RTU两种模式的区别、优缺点

    MODBUS ASCII协议和RTU协议的比较: 

    协议 开始标记 结束标记 校验 传输效率 程序处理
    ASCII :(冒号) CR,LF LRC 直观,简单,易调试
    RTU CRC 稍复杂

    MODBUS的ASCII协议和RTU协议相比,MODBUS ASCII协议拥有开始和结束标记,而MODBUS RTU却没有,所以ASCII协议的程序中对数据包的处理能更加方便。MODBUS ASCII协议的DATA域传输的都是可见的ASCII字符,因此在调试阶段就显得更加直观,另外它的LRC校验程序也比较容易编写,这些都是MODBUS ASCII的优点。MODBUS ASCII的主要缺点是传输效率低,因为它传输的都是可见的ASCII字符,原来用RTU传输的数据每一个字节,用ASCII的话都要把这个字节拆分两个字节,比如RTU传输一个十六进制数0xF9,ASCII就需要传输字符'F'和字符'9',对应的ASCII码0x46和0x39两个字节,这样它的传输的效率肯定就比RTU低。所以一般来说,如果所需要传输的数据量较小可以考虑使用ASCII协议,如果所需传输的数据量比较大,最好能使用RTU协议。
    另外,由于ASCII协议有开始标志和结束标志,所以一个数据包之间的各字节间的传输间隔时间可以大于1秒,而MODBUS RTU方式下,由于没有规定开始和结束标记,所以协议规定每两个字节之间发送或者接收的时间间隔不能超过3.5倍字符传输时间。如果两个字符时间间隔超过了3.5倍的字符传输时间,就认为一帧数据已经接收,新的一帧数据传输开始,所以RTU方式下两个字节间传输间隔有时间要求。MODBUS 的ASCII和RTU两种协议的这一区别可能决定某些应用场合只能选用其中一种协议。

    四、modbus功能码

     

    下表列出MODBUS支持的部分功能代码:以十进制表示。

    表1.1 MODBUS部分功能码

    代码

    中文名称

    寄存器PLC地址

    位操作/字操作

    操作数量

    01

    读线圈状态

    00001-09999

    位操作

    单个或多个

    02

    读离散输入状态

    10001-19999

    位操作

    单个或多个

    03

    读保持寄存器

    40001-49999

    字操作

    单个或多个

    04

    读输入寄存器

    30001-39999

    字操作

    单个或多个

    05

    写单个线圈

    00001-09999

    位操作

    单个

    06

    写单个保持寄存器

    40001-49999

    字操作

    单个

    15

    写多个线圈

    00001-09999

    位操作

    多个

    16

    写多个保持寄存器

    40001-49999

    字操作

    多个

     

     

    modbus协议的数据主要分为四类:离散量输入、线圈状态、输入寄存器、保持寄存器。离散量输入对应开入(遥信),线圈状态对应哪开出(遥控),输入寄存器对应只读的模拟量(遥测),保持寄存器对应可读可写的模拟量(遥调)。
    1.1功能码说明

        功能码可以分为位操作和字操作两类。位操作的最小单位为BIT,字操作的最小单位为两个字节。

            【位操作指令】    读线圈状态01H,读(离散)输入状态02H,写单个线圈06H和写多个线圈0FH。

            【字操作指令】    读保持寄存器03H,写单个寄存器06H,写多个保持寄存器10H。

    1.2Modbus数据模型

    Modbus中,数据可以分为两大类,分别为CoilRegister,每一种数据,根据读写方式的不同,又可细分为两种(只读,读写)。
    Modbus四种数据类型:

    数据名称

    数据含义

    读写状态

    Discretes Input

    位变量

    只读

    Coils

    位变量

     读写

    Input Registers

    16-bit类型

    只读

    Holding Registers

    16-bit类型

    读写

     

    1.3寄存器地址分配

    表1.3 MODBUS寄存器地址分配

    寄存器PLC地址

    寄存器协议地址

    适用功能

    寄存器种类

    读写状态

    描述

    00001-09999

    0000H-FFFFH

    01H 05H 0FH

    线圈状态

    可读可写

     

    10001-19999

    0000H-FFFFH

    02H

    离散输入状态

    可读

     

    30001-39999

    0000H-FFFFH

    04H

    输入寄存器

    可读

    每个寄存器表示一个16-bit无符号整数(0~65535

    40001-49999

    0000H-FFFFH

    03H 06H 0FH

    保持寄存器

    可读可写

    两个连续16-bit寄存器表示一个浮点数

    50001-59999

    0000H-FFFFH

    03H 04H 06H 0FH

    ASCII字符

    可读可写

    每个寄存器表示两个ASCII字符

     

    1.4寄存器种类说明

    表1.4 MODBUS寄存器种类说明

    寄存器种类

    说明

    PLC类比

    举例说明

    线圈

    状态

    输出端口。可设定端口的输出状态,也可以读取该位的输出状态。可分为两种不同的执行状态,例如保持型或边沿触发型。

    DO

    数字量输出

    电磁阀输出,MOSFET输出,LED显示等。

    离散

    输入状态

    输入端口。通过外部设定改变输入状态,可读但不可写。

    DI

    数字量输入

    拨码开关,接近开关等。

    保持

    寄存器

    输出参数或保持参数,控制器运行时被设定的某些参数。可读可写。

    AO

    模拟量输出

    模拟量输出设定值,PID运行参数,变量阀输出大小,传感器报警上限下限。

    输入

    寄存器

    输入参数。控制器运行时从外部设备获得的参数。可读但不可写。

    AI

    模拟量输入

    模拟量输入

     

    1.5 PLC地址和协议地址区别

        PLC地址可以理解为协议地址的变种,在触摸屏和PLC编程中应用较为广泛。

    1.5.1寄存器PLC地址

        寄存器PLC地址指存放于控制器中的地址,这些控制器可以是PLC,也可以使触摸屏,或是文本显示器。PLC地址一般采用10进制描述,共有5位,其中第一位代码寄存器类型。第一位数字和寄存器类型的对应关系如表1所示。PLC地址例如40001、30002等。

    1.5.2寄存器协议地址

        寄存器协议地址指指通信时使用的寄存器地址,例如PLC地址40001对应寻址地址0x0000,40002对应寻址地址0x0001,寄存器寻址地址一般使用16进制描述。再如,PLC寄存器地址40003对应协议地址0002,PLC寄存器地址30003对应协议地址0002,虽然两个PLC寄存器寄存器通信时使用相同的地址,但是需要使用不同的命令访问,所以访问时不存在冲突。

     

    五、注意事项

    1、MODBUS 3.5T是如何计算的?

    T = 1000毫秒*(1起始位+数据位+奇偶校验+停止位)/波特率

    如果你的通讯方式是:波特率115200(表示每秒传输多少字符),数据位8,无奇偶校验。那么你发送一个字符的时间是:T=1000* (1起始位+8数据位+0奇偶校验+1停止位)/ 115200=0.087ms。
    发送端:发送一帧后延时7*T(其中3.5T是停止时间,3.5T是起始时间)再发送第二帧,保证一帧数据里头各字节间间隔延时不能超过1.5T。
    接收端:接收一个字节,查询2T时间,是否有接收到下一个字节,有则这帧数据未完,继续循环接收;没有则默认这帧已经接收完毕。

    2、串口超时时间设置

    COMMTIMEOUTS timeout;

    //填充timeout结构

    GetCommTimeouts(m_h232Port,&timeout);

    timeout.ReadIntervalTimeout=100;//两字符之间最大的延时

    timeout.ReadTotalTimeoutConstant=500;

    timeout.ReadTotalTimeoutMultiplier=0;//读取每字符间的超时

    timeout.WriteTotalTimeoutConstant=2000;

    timeout.WriteTotalTimeoutMultiplier=60;//写入每字符间的超时

    BOOLerror=SetCommTimeouts(m_hPort,&timeout);

    ReadIntervalTimeout:两字符之间最大的延时,当读取串口数据时,一旦两个字符传输的时间差超过该时间,读取函数将返回现有的数据。设置为0表示该参数不起作用。 
    ReadTotalTimeoutMultiplier:读取每字符间的超时。 
    ReadTotalTimeoutConstant:一次读取串口数据的固定超时。所以在一次读取串口的操作中,其超时为ReadTotalTimeoutMultiplier乘以读取的字节数再加上 ReadTotalTimeoutConstant。将ReadIntervalTimeout设置为MAXDWORD,并将ReadTotalTimeoutMultiplier 和ReadTotalTimeoutConstant设置为0,表示读取操作将立即返回存放在输入缓冲区的字符。 
    WriteTotalTimeoutMultiplier:写入每字符间的超时。 
    WriteTotalTimeoutConstant:一次写入串口数据的固定超时。所以在一次写入串口的操作中,其超时为WriteTotalTimeoutMultiplier乘以写入的字节数再加上 WriteTotalTimeoutConstant。 

    3、在程序中如果要用到多个串口,而且还要做很多复杂的处理,那么最好不用MSComm通讯控件,网络上有很多封装好的串口类。

    C++ class for Win32 serial ports:http://www.naughter.com/serialport.html

    CSerialPort:https://github.com/itas109/CSerialPort

    4、如何写稳定的modbus代码?

    需要从稳定性和易读性来考虑,如果稳定性较差会造成系统控制故障,如果易读性差就会造成难以维护,这些控制指令之间差别很小,如果一个一个单独写命令,非常容易出错。对应举措如下:

    1)避免每个指令写一部分代码,需要统一处理,比如校验函数,发送函数,接收函数等。

      通信协议已知,从中可以知道通信的实际数据长度(不包含包头包尾和校验的部分),所以可以控制读写多少个字节,并且可以知道什么时候启动校验,那些数据参与校验计算。

    2)为指令建立指令列表,这样后来需要添加功能,就可以直接把指令字加入列表即可。

    3)适当抽象。为每个指令的动作写回调函数,这样就可以在应用层,用一句简单的回调函数指针直接操作具体的动作函数,而不是应用逻辑层操作具体的驱动层面的接口。

    4)超时,必须有超时机制。通信失败怎么处理?通信之后一般线断了怎么处理?不能让系统死等后面的几个字节发过来。

    5)接收超时机制,不能依靠数传输的字节个数来停止接收来和区分帧间隔,因为可能通信就是断掉了,所以要按照协议,串口通信情况下3~5个T空闲就认为一帧结束。也可以通过协议事先计算出接收数据的总时间(字符数*(字符时间+字符间间隔时间)),使用该使用作为等待超时时间,但最长超时时间不能超过5T时间。

    6)响应超时机制,Modbus是请求/应答式通信,那么主机就需要知道到底多久从机才会应答,主机等待从机应答的最长时间就是从机的最大回复间隔,超过这个时间后从机即使已经完成计算也不能回复,因为此时主机可能已经开始给其他从机发送数据了。

    7)如果通信都是由你发起的,那么无论此次通信是完成还是超时或失败,都应该关闭通信端口。

    8)如果是线程中操作串口,可以提升线程优先级,让操作系统在一定程度上提高串口读写性能。

    9)ModbusRTU设备参数设置如下:
    (1)内部属性:单击“查看设备内部属性” ,点击按钮进入内部属性
    (2)最小采集周期:组态软件对设备进行操作的时间周期, 单位为 ms, 默认为100ms,根据采集数据量的大小,设置值可适当调整
    (3)设备地址:必须和实际设备的地址相一致,范围为0-255,默认值为 0。
    (4)通讯等待时间:通讯数据接收等待时间,默认设置为 200ms,根据采集数据量的大小,设置值可适当调整。
    (5)快速采集次数:对选择了快速采集的通道进行快采的频率(已不使用,为与老驱动兼容,故保留,无需设置) 。
    (6)16位整数解码顺序:调整字元件的解码顺序,对于Modicon PLC 及标准 PLC设备,使用默认值即可。
    16 位整数解码顺序 举例:0x0001
    0―12 表示字元件高低字节不颠倒(默认值) 表示 1
    1―21 表示字元件高低字节颠倒 表示 256
    (7)32位整数解码顺序:调整双字元件的解码顺序,对于Modicon PLC,请设置为“2-3412”顺序解码。
    32 位整数解码顺序 举例: 0x0000 0001
    0―1234 表示双字元件不做处理直接解码(默认值) 表示 1
    1―2143 表示双字元件高低字不颠倒,但字内高低字节颠倒 表示256
    2—3412表示双字元件高低字颠倒,但字内高低字节不颠倒  表示65536
    3—4321表示双字元件内4个字节全部颠倒 表示 16777216
    (8)32位浮点数解码顺序:调整双字元件的解码顺序,对于Modicon PLC,请设置为“2-3412”顺序解码。
    32 位浮点数解码顺序 举例:0x3F80 0000
    0―1234 表示双字元件不做处理直接解码(默认值) 表示 1.0
    1―2143 表示双字元件高低字不颠倒,但字内高低字节颠倒 表示-5.78564e-039
    2—3412表示双字元件高低字颠倒,但字内高低字节不颠倒  表示2.27795e-041
    3—4321表示双字元件内4 个字节全部颠倒 表示 4.60060e-041
    (9)校验方式: 选择LRC校验值的组合方式, 对于 Modicon PLC及标准 PLC 设备,
    使用默认设置即可。
    0—LH[低字节,高字节]:校验结果为2 个字节,低字节在前,高字节在后。
    1—HL[高字节,低字节]:校验结果为2 个字节,高字节在前,低字节在后。默认值。
    (10)分块采集方式:驱动采集数据分块的方式,对于Modicon PLC及标准 PLC设备,使用默认设置可以提高采集效率。
    0— 按最大长度分块:采集分块按最大块长处理,对地址不连续但地址相近的多个分块,分为一块一次性读取,以优化采集效率。
    1— 按连续地址分块:采集分块按地址连续性处理,对地址不连续的多个分块,每次只采集连续地址,不做优化处理。
    例如:有4区寄存器地址分别为 1~5,7,9~12的数据需采集,如果选择“0-按最大长度分块” ,则两块可优化为地址1~12的数据打包1次完成采集;如果选择“1-按连续地址分块” ,则需要采集 3 次。
    (11)4区16 位写功能码选择:写 4 区单字时功能码的选择,这个属性主要是针对自己制作设备的用户而设置的,这样的设备4区单字写可能只支持 0x10 功能码,而不支持0x06 功能码。
    0—0x06:单字写功能码使用0x06。
    1—0x10:单字写功能码使用0x10。
    注意:
    (1). “解码顺序”及“校验方式”设置:主要是针对非标准 ModbusRTU 协议的不同解码及校验顺序。当用户通过本驱动软件与设备通讯时,如果出现解析数据值不对,或者通讯校验错误(通讯状态为3),可与厂家咨询后对以上两项进行设置。而对于ModiconPLC及支持标准ModbusRTU 的 PLC 及控制器等设备,一般需将“32位整数解码顺序”和“32位浮点数解码顺序”设置为“2-3412” 。 另外,在使用本驱动与“Modbus 串口数据转发设备”构件通讯时, “解码顺序”及“校验方式”均需按默认值设置,否则会导致通讯失败或解析数据错误。
    (2). “分块采集方式”设置:主要是针对非标准 ModbusRTU协议设备。当用户通过本驱动软件与设备通讯时,如果按默认“0-按最大长度分块”时,出现读取连续地址正常,而不连续地址不正常时,可与厂家咨询,并设置为“1-按连续地址分块方式”尝试是否可正常通讯。 而对于 Modicon PLC 及支持标准 ModbusRTU 的 PLC 及控制器等设备,直接使用默认设置即可,这样可以提高采集效率。
    http://blog.csdn.net/gshgsh1228/article/details/51218306

    5、lrc和crc校验算法

     

    //--------------------------------------------------------------------------
    // Constants
    //--------------------------------------------------------------------------
    static const uint16_t modbus_crc_table[256] = {
       0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
       0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
       0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
       0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
       0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
       0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
       0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
       0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
       0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
       0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
       0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
       0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
       0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
       0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
       0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
       0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
       0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
       0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
       0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
       0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
       0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
       0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
       0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
       0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
       0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
       0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
       0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
       0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
       0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
       0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
       0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
       0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
    };
    
    //--------------------------------------------------------------------------
    // Modbus functions
    //--------------------------------------------------------------------------
    uint8_t modbus_lrc_calc(uint8_t *data, uint16_t len)
    {
       uint8_t lrc = 0U;
       int i;
    
       for (i = 0U; i < len; i++)
       {
          lrc += data[i];
       }
       lrc = (0xFFU - lrc)+1U;
       return(lrc);
    }
    
    uint16_t modbus_crc_calc(uint8_t *buffer, uint16_t size)
    {
       uint16_t crc = 0xFFFFU; 
       uint8_t nTemp;
    
        while (size--)
        {
            nTemp = *buffer++ ^ crc;
            crc >>= 8;
            crc  ^= modbus_crc_table[(nTemp & 0xFFU)];
        }
    
       return(crc);
    }

     

    LRC算出来的是16进制的字节值,若发送的数据是字符串形式,不需任何转换,直接放在字符串最后位置就行了。若发送的数据是数组形式,则需要转换为ASCII值,即由1字节的16进制转换为2字节的ASCII值,4D应该转换为34 44。
    如果你的发送指令是:com.output="xxxxx",就是字符串形式;
    如果发送指令形式是:com.output=A[],就是数组形式。
    但不管是哪种形式,ModBus ASCII模式最终在数据线上的数据都是ASCII值。字符串形式的数据,编译软件会自动转换。

    6、调试工具

    Modbus Poll是一个Modbus管理模拟器软件,帮助开发人员进行管理和监控的Mod bus数据区在同一时间和模拟Mod bus协议。支持Modbus RTU / ASCII和Modbus TCP / IP协议。

    下载地址:http://www.downcc.com/soft/25945.html

    modbus slave是一款功能强大的modbus子设备模拟工具,可以帮助modbus通讯设备开发人员进行modbus通讯协议的模拟和测试,用于模拟、测试、调试modbus通讯设备。

    下载地址:http://www.ddooo.com/softdown/70166.htm

     7、modbus开源项目

    https://github.com/stephane/libmodbus

    vc2008 版本下载:http://download.csdn.net/download/byxdaz/10011387

     

    参考资料

    http://www.cnblogs.com/luomingui/archive/2013/06/14/Modbus.html

    展开全文
  • Modbus的十大问题

    千次阅读 2012-07-09 17:06:16
    今天还有人问我modbus的问题,就想把着自己对于这个简单协议 的一点小理解写了出来,一是方便一些朋友查阅,另外也是为了防止遗忘。当然水平有限可能有错误或者不准确之处,真诚的欢迎大家批评指正,让我与您共同...
    老伙计原创,如转载请注明出处
     
    今天还有人问我modbus的问题,就想把着自己对于这个简单协议
    的一点小理解写了出来,一是方便一些朋友查阅,另外也是为了防止遗忘。当然水平有限可能有错误或者不准确之处,真诚的欢迎大家批评指正,让我与您共同进步。
     
    1. 有了RTU为啥还要ascii?
    个人理解认为,ascii主要是为了在终端上使用(想想linux为啥都是在命令行下面就好理解了),方便看到通讯的过程,经常在楼宇等对控制要求不高的领域会采用。这也就可以解释了为啥在ascii有加了头尾,既然是为了看,那就看的清楚些。
    2. Modbus和J-bus以及M-bus分别是什么关系?
    Mobus和JBus是近亲,与M-Bus没有任何关系。
    J-Bus基本采用了Modbus的帧结构和定义,仅仅是在寄存器的地址方面有些区别。
    M-Bus的全称是Meter-Bus,是仪表总线,欧洲使用的较多,帧结构是给予iec60870的,顺便提一句,Profibus的帧结构也是给予Iec60870的。
    3.Modbus的其实地址到底是0还是1?
    这个问题现在比较混乱,怎么用的都有,这也是Modbus不好的一个小地方。因为modbus是modicon发明的,自然他的寄存器地址的排布是从1开始的,但是在通讯的时候又是从0开始的,这也是显然的,0如果不使用,不是浪费么。这就导致了混乱,寄存器定义部分和协议定义部分一致起来,就不会产生歧义了。如果读取的都是整个寄存器,一般很容易发现错位的问题,但是如果都是浮点类型,就很难发现了,本人就见到N多人在这个问题上被卡过。
    4.Modbus的最大缺点是什么?
    modbsu的缺点太多(比如帧序号,比如数据类型太少,还比如轮训效率太低,。。。。。),一时还真说不好哪一个是最,非要说一个那就是,没有帧序号吧,如果从设备应答的慢了,主设备读取下一帧数据,这个时候恰好从设备回复上一帧的数据,就会导致错误,这样的情况是真实发生过的。
    5.RTU和TCP有何不同?
    基本是相同,主要有两点。一个是tcp加了帧序号,是针对问题4的解决办法(rtu之所以没有升级,增加序号,是因为发生的概率较小,但是在网络上这样的情况是有很大可能性发生的)
    第二个就是tcp帧本身有了校验,就不需要modbus的校验了
    6.寄存器地址必须是00001至09999是离散输出(线圈)
    10001至19999是离散输入(触点)
    30001至39999是输入寄存器(通常是模拟量输入)
    40001至49999是保持寄存器
    不是的。事实上modbus是有两种地址排布模式,也就是“separate block”方式和“one block”方式,前一种很常见,很多厂家都采用这样的方式,后一种也有一些比如一些空调设备厂家的就是这样的。
    第一种不同的寄存器是不同的地址;
    第二种不同的寄存器实际上是重叠的。
    7.Modbustcp的端口号?
    502,相信很多人都知道,这是唯一分给工业标准的端口号,自豪去吧。当然了,实际应用中不见得非要用这个,只要两端对应好就可以了。
    8.modbus符合Iso/OSI模型么?
    其实我我个人认为不太符合,尽管这两年modbus基金会,吧他的协议问题都分层分块了,但是最开始设计的时候就不是给予这个结构考虑的,后往上靠,总让人觉得不伦不类的。
    9.Daniel/enron/OMNI MODBUS是啥?
    modbus的扩充标准,主要是数据类型做了扩充。其实标准就像是路,走的人多了,路也就成为路了。
    10.modbus浮点数为啥有4个顺序?
    因为一个浮点数占用4个字节,2个寄存器,因为标准没有规定浮点数咋读取(好像是modbus制定的时候浮点数标准还没有制定呢),人们怎么处理的都有,常见的就是4个字节的处理办法,但是就算是都用了4个字节,但是大家的顺序还是千奇百怪(说是千奇百怪,实际上就4种)
    11.rtps是啥?
    写到了这里,发现题目弄错了,但是也懒得修改了,现今啥都喜欢弄个十大,咱也就不改了,嘿嘿。
    随着工业以太网的热火朝天,modbus -tcp/ip与其他的工业以太网协议相比,明显弱了很多。所以modbus基金会赶紧制定了rtps,主要是赶上这一波。主要是增加了发布和订阅机制。这里补充说明一些,发布和订阅机制已经在很多协议和规范里面采用了(比如OPC,bacnet, IEC61850.。。。。。),在现今如果说一个以太网的协议还不支持这个,确实有点说不过去了。
    展开全文
  • ModBus-RTU详解

    万次阅读 多人点赞 2018-05-27 19:40:15
    Modbus 一个工业上常用的通讯协议、一种通讯约定。Modbus协议包括RTU、ASCII、TCP。其中MODBUS-RTU最常用,比较简单,在单片机上很容易实现。虽然RTU比较简单,但是看协议资料、手册说得太专业了,起初很多内容都很...
  • MODBUS协议最简单又是最直白的解释

    万次阅读 多人点赞 2018-01-11 10:00:36
    Modbus是一种单主站的主/从通信模式。Modbus网络上只能有一个主站存在,主站在 Modbus网络上没有地址,从站的地址范围为 0 - 247,其中 0 为广播地址,从站的实际地址范围为 1 - 247。 Modbus通信标准协议可以通过...
  • Modbus

    2020-05-12 09:44:35
    为什么要用modbus协议 modbus在公共设备上用的比较多,包括PLC、变频器、温控器、电脑都可以进行modbus通讯。 拿PLC举例,我们已经可以实现开关量、模拟量的控制都可以实现了,进行温度的测量,温度输出控制都可以了...
  • Modbus协议(翻自wiki)

    千次阅读 2018-10-31 13:49:34
    Modbus 译文 Modbus 来自维基百科,自由的百科全书 Modbus 是一种串行通信协议,最初由Modicon(现为施耐德电气)于 1979 年出版,用于其可编程逻辑控制器( PLC )。 Modbus 已成为约定俗成的标准通信协议,...
  • Modbus应用协议详解

    千次阅读 2019-03-18 18:38:23
    Modbus应用协议缩略语协议描述服务器正常响应服务器异常响应三种PDUmb_req_pdumb_rsp_pdumb_excep_rsp_pdu数据编码Modbus数据模型Modbus模型实现的实例 缩略语 协议描述 Modbus是一个请求/应答协议,并且提供功能码...
  • Modbus 协议中文版完整版
  • STM32-modbus rtu 之主机程序

    万次阅读 多人点赞 2020-09-03 19:19:08
    STM32-modbus rtu 之主机程序
  • Modbus TCP和Modbus Rtu协议的区别

    万次阅读 2013-06-26 13:20:28
    Modbus rtu和Modbus tcp两个协议的本质都是MODBUS协议,都是靠MODBUS寄存器地址来交换数据;但所用的硬件接口不一样,Modbus RTU一般采用串口RS232C或RS485/422,而Modbus TCP一般采用以太网口。现在市场上有很多...
  • Modbus Poll 设置Modbus TCP通信超时时间

    万次阅读 2015-12-30 21:06:31
    使用Modbus Poll可以轻松的用PC模拟Modbus主机,可以建立 Modbus RTU Modbus ASCII Modbus-TCP通信。 当使用Modbus TCP通信时,可以根据结点的多少设置一下超时时间,默认可能为:3000ms(3秒)有点长。  毕竟TCP...
  • 经过这几天的学习与调试,终于在STM32F103VCT6+W5500(SPI1)+Freemodbus 平台上,实现Modbus-TCP协议的功能。其实很简单,只要熟悉Modbus-RTU通讯,明白Modbus帧的结构等,Modbus-TCP只是在原来的帧结构上加个头,去...
  • 一、串口调试工具SSCOM 可以自动识别串口,hex格式发送和接收,字符格式发送和接收,可以自定义发送命令及自动发送、循环发送命令。
  • ModbusPoll及ModbusSlave安装及使用指南

    万次阅读 多人点赞 2018-05-20 10:15:02
    1. ModbusPoll及ModbusSlave介绍 ModbusPoll是一个主站设备仿真软件,支持多文档接口,即可以同时监视多个从站设备及数据域。ModbusSlave是一个从站设备仿真软件,它用于接收主设备的命令包,并回送数据包;可用于...
  • Modbus rtu CRC在线计算

    万次阅读 2011-09-20 11:16:49
    自己想写个Modbus rtu的计算,C#写了半天都不对,还是先弄个在线计算的先用。 Rtu的选Hex。 如 发送命令:02 03 00 05 00 02 看结果  CRC-16 (Modbus) 0x39D4 命令码和功能码之间,可用空格分隔。
  • modbus slave和modbus poll使用说明

    万次阅读 多人点赞 2018-07-23 13:42:03
    modbus slave和modbus poll使用说明 1.使用环境:  win7/win10 32/64位系统  Virtual Serial Port Driver 9.0 虚拟com端口工具 2.说明:最近项目开发使用到了modbus协议,由于刚接触这个协议,在使用第三方工具...
  • modbus poll 6.3.1破解版 附注册码

    万次阅读 2018-10-06 21:12:01
    http://www.ddooo.com/softdown/70167.htm 1、下载解压缩,根据需求选择安装32位或64位版本; 2、成功安装后,点击菜单...gt;... 3、序列号:5A5742575C5D10 ...4、打开软件,modbus poll已经可以无限制免费使用。 ...
1 2 3 4 5 ... 20
收藏数 14,793
精华内容 5,917
关键字:

modbus