Modbus TCPIP基础知识-------------ModbusTCPIP协议概述(一)

1 ModbusTcp

简单的理解一下Modbus TCP/IP协议的内容,就是去掉了modbus协议本身的CRC校验,增加了MBAP 报文头。TCP/IP上的MODBUS的请求/响应如下图所示:

TCPIPmodbus请求和响应

1.1 MBAP报文

首先来看一下,MBAP 报文头都包括了哪些信息和内容

长度描述客户机服务器
事务元标识符2个字节MODBUS请求/响应事务处理的识别码客户机启动服务器从接收的请求中重新复制
协议标识符2个字节0=MODBUS协议客户机启动服务器从接收的请求中重新复制
长度2个字节以下字节的数量客户机启动(请求)服务器(响应)启动
单元标识符1个字节串行链路或其它总线上连接的远程从站的识别码客户机启动服务器从接收的请求中重新复制

事务元标识符(2个字节):用于事务处理配对。在响应中,MODBUS服务器复制请求的事务处理标识符。这里在以太网传输中存在一个问题,就是先发后至,我们可以利用这个事务处理标识符做一个TCP序列号,来防止这种情况所造成的数据收发错乱(这里我们先不讨论这种情况,这个事务处理标识符我们统一使用0x00,0x01)
协议标识符(2个字节):modbus协议标识符为0x00,0x00
长度(2个字节):长度域是下一个域的字节数,包括单元标识符和数据域。
单元标识符(1个字节):该设备的编号。(可以使用PLC的IP地址标识)。

在MODBUS MODBUS+串行链路子网中对设备进行寻址时,这个域是标识设备地址。在这种情况下,“Unit Identifier”携带一个远端设备的MODBUS从站地址:

  • 如果MODBUS服务器连接到MODBUS+或MODBUS串行链路子网,并通过一个桥或网关配置地址这个服务器,MODBUS单元标识符对识别连接到网桥或网关后的子网的从站设备是必需的。目的IP地址识别了网桥本身的地址,而网桥则使用MODBUS单元标识符将请求转交给正确的从站设备。
  • 分配串行链路上MODBUS从站设备地址为1~247(10进制),地址0作为广播地址。
    对 TCP/IP 来说,利用IP地址寻址MODBUS服务器;因此,MODBUS单元标识符是无用的。必需使用值0xFF。
  • 当对直接连接到TCP/IP网络上的MODBUS服务器寻址时,建议不要在“单元标识符”域使用有效的MODBUS从站地址。在一个自动系统中重新分配IP地址的情况下,并且如果以前分配给MODBUS服务器的IP地址又被指配给网关,使用一个有效的从站地址可能会由于网关的路由不畅而引起麻烦。使用无效的从站地址,网关仅是简单地废弃MODBUD PDU,而不会有任何问题。建议:在采用0xFF作为“单元标识符”的无效值。

    注:0也可以用作与MODBUS/TCP设备直接通信。

1.2 MODBUS请求的生成

在收到来自用户应用的需求后,客户端必须生成一个MODBUS请求,并发送到TCP管理。下表显示MODBUS请求ADU编码:

类型描述字节大小实例
MBAP报文头事务处理标识符Hi10x15
事务处理标识符Lo10x01
协议标识符20x0000
长度20x0006
单元标识符10xFF
MODBUS请求功能码10x03
起始地址20x0005
寄存器数量20x0001

1.3 MODBUS响应的生成

一旦处理请求,MODBUS 服务器必须使用适当的MODBUS服务器事务处理生成一个响应,并且必须将响应发送到TCP管理组件。

根据处理结果,可以生成两类响应:

  • 肯定的MODBUS响应:
    • 响应功能码 = 请求功能码
  • MODBUS异常响应:
    • 目的是为客户机提供与处理过程检测到的错误相关的信息
    • 响应功能码 = 请求功能码+0x80
    • 提供异常码来表明出错的原因。
异常码MODBUS名称备注
01非法的功能码服务器不了解功能码
02非法的数据地址与请求有关
03非法的数据值与请求有关
04服务器故障在执行过程中,服务器故障
05确认服务器接受服务调用,但是需要相对长的时间完成服务。因此,服务器仅返回一个服务调用接收的确认。
06服务器繁忙服务器不能接受MODBUS请求PDU。客户应用由责任决定是否和何时重发请求。
0A网关故障网关路经是无效的。
0B网关故障目标设备没有响应。网关生成这个异常信息。

通过上面的两步,一个Modbus TCP的客户端连接已经建立起来了,下面我们就来分析Modbus TCP协议的具体内容与实现方式了。

2 Modbus介绍

2.1 MODBUS数据模型

基本表格对象类型访问类型内容
离散量输入单个比特只读I/O系统提供这种类型数据
线圈单个比特读写通过应用程序改变这种类型数据
输入寄存器16比特字只读I/O系统提供这种类型数据
保持寄存器16比特字读写通过应用程序改变这种类型数据

2.2 公共功能码定义

功能码
子码十六进制
比特访问
物理离散量输入读输入离散量0202
内部比特或物理线圈读线圈0101
写单个线圈0505
写多个线圈150F
16比特访问输入寄存器读输入寄存器0404
内部存储器或物理输出存储器读多个寄存器0303
写单个寄存器0606
写多个寄存器1610
读/写多个寄存器2317
屏蔽写寄存器2216
文件记录访问读文件记录20614
写文件记录21615

3 功能码描述

我们直接用实例来说明。

3.1 01(0x01)功能码—读线圈

在一个远程设备中,使用该功能码读取线圈的1 至2000 连续状态。请求PDU 详细说明了起始地址,即指定的第一个线圈地址和线圈编号。从零开始寻址线圈。因此寻址线圈1-16 为0-15。

根据数据域的每个比特将响应报文中的线圈分成为一个线圈。指示状态为1= ON 和0= OFF。

第一个数据字节的LSB(最低有效位)包括在询问中寻址的输出。其它线圈依次类推,一直到这个字节的高位端为止,并在后续字节中从低位到高位的顺序。

如果返回的输出数量不是八的倍数,将用零填充最后数据字节中的剩余比特(一直到字节的高位端)。字节数量域说明了数据的完整字节数。

请求与响应格式

请求PDU

功能码1个字节0x01
起始地址2个字节0x0000至0xFFFF
线圈数量2个字节1至2000(0x7D0)

响应PDU

功能码1个字节0x01
字节数1个字节N*
线圈状态N个字节n=N或N+1

注:*N=输出数量/8,如果余数不等于0,那么N=N+1

错误

差错码1个字节功能码+0x80
异常码1个字节01或02或03或04

这是一个请求读离散量输出20-38 的实例:

请求响应
域名十六进制域名十六进制
功能01功能01
起始地址Hi00字节数03
起始地址Lo13输出状态27-20CD
输出数量Hi00输出状态35-286B
输出数量Lo13输出状态38-3605

将输出27-20 的状态表示为十六进制字节值CD,或二进制1100 1101。输出27 是这个字节的MSB,输出20 是LSB。
通常,将一个字节内的比特表示为MSB 位于左侧,LSB 位于右侧。第一字节的输出从左至右为27至20。下一个字节的输出从左到右为35至28。当串行发射比特时,从LSB向MSB传输:20 . . .27、28 . . . 35 等等。
在最后的数据字节中,将输出状态38-36表示为十六进制字节值05,或二进制0000 0101。输出38 是左侧第六个比特位置,输出36 是这个字节的LSB。用零填充五个剩余高位比特。

注:用零填充五个剩余比特(一直到高位端)。

3.2 02(0x02)功能码—读离散量输入

在一个远程设备中,使用该功能码读取离散量输入的1 至2000 连续状态。请求PDU 详细说明了起始地址,即指定的第一个输入地址和输入编号。从零开始寻址输入。因此寻址输入1-16 为0-15。

根据数据域的每个比特将响应报文中的离散量输入分成为一个输入。指示状态为1= ON 和0=OFF。第一个数据字节的LSB(最低有效位)包括在询问中寻址的输入。其它输入依次类推,一直
到这个字节的高位端为止,并在后续字节中从低位到高位的顺序。

如果返回的输入数量不是八的倍数,将用零填充最后数据字节中的剩余比特(一直到字节的高位端)。字节数量域说明了数据的完整字节数。

请求PDU

功能码1个字节0x02
起始地址2个字节0x0000至0xFFFF
线圈数量2个字节1至2000(0x7D0)

响应PDU

功能码1个字节0x82
字节数1个字节N*
线圈状态N*x1个字节

注:*N=输出数量/8,如果余数不等于0,那么N=N+1

错误

差错码1个字节功能码+0x82
异常码1个字节01或02或03或04

这是一个请求读离散量输入197-218 的实例:

请求响应
域名十六进制域名十六进制
功能02功能02
起始地址Hi00字节数03
起始地址LoC4输出状态204-197AC
输出数量Hi00输出状态212-205DB
输出数量Lo16输出状态218-21335

将离散量输入状态204-197表示为十六进制字节值AC,或二进制1010 1100。输入204是这个字节的MSB,输入197 是这个字节的LSB。

将离散量输入状态218-213表示为十六进制字节值35,或二进制0011 0101。输入218位于左侧第3 比特,输入213 是LSB。

注:用零填充2 个剩余比特(一直到高位端)。

3.3 03(0x03)功能码—读保持寄存器

在一个远程设备中,使用该功能码读取保持寄存器连续块的内容。请求PDU说明了起始寄存器地址和寄存器数量。从零开始寻址寄存器。因此,寻址寄存器1-16 为0-15
将响应报文中的寄存器数据分成每个寄存器有两字节,在每个字节中直接地调整二进制内容。
对于每个寄存器,第一个字节包括高位比特,并且第二个字节包括低位比特。

请求

功能码1个字节0x03
起始地址2个字节0x0000至0xFFFF
寄存器数量2个字节1至125(0x7D)

响应

功能码1个字节0x03
字节数1个字节2xN*
寄存器值N*x2个字节

注:*N=输出数量/8,如果余数不等于0,那么N=N+1

错误

差错码1个字节0x83
异常码1个字节01或02或03或04

这是一个请求读保持寄存器108-110 的实例:

请求响应
域名十六进制域名十六进制
功能03功能03
高起始地址00字节数06
低起始地址6B寄存器值Hi(108)02
高寄存器编号00寄存器值Lo(108)2B
低寄存器编号03寄存器值Hi(109)00
寄存器值Lo(109)00
寄存器值Hi(110)00
寄存器值Lo(110)64

将寄存器108的内容表示为两个十六进制字节值02 2B,或十进制555。将寄存器109-110的内容分别表示为十六进制00 00 和00 64,或十进制0 和100。

3.4 04(0x04)功能码—读输入寄存器

在一个远程设备中,使用该功能码读取1 至大约125 的连续输入寄存器。请求PDU 说明了起始地址和寄存器数量。从零开始寻址寄存器。因此,寻址输入寄存器1-16 为0-15
将响应报文中的寄存器数据分成每个寄存器为两字节,在每个字节中直接地调整二进制内容。
对于每个寄存器,第一个字节包括高位比特,并且第二个字节包括低位比特。

请求

功能码1个字节0x04
起始地址2个字节0x0000至0xFFFF
寄存器数量2个字节0x0000至0x007D

响应

功能码1个字节0x04
字节数1个字节2xN*
寄存器值N*x2个字节

注:*N=输入寄存器的数量

错误

差错码1个字节0x84
异常码1个字节01或02或03或04

这是一个请求读输入寄存器9的实例:

请求响应
域名十六进制域名十六进制
功能04功能04
起始地址Hi00字节数02
起始地址Lo08输入寄存器值Hi(9)00
输入寄存器数量Hi00输入寄存器值Lo(9)0A
输入寄存器Lo01

将输入寄存器9 的内容表示为两个十六进制字节值00 0A,或十进制10。

3.5 05(0x05)功能码—写单个线圈

在一个远程设备上,使用该功能码写单个输出为ON 或OFF。
请求数据域中的常量说明请求的ON/OFF状态。十六进制值FF 00请求输出为ON。十六进制值00 00 请求输出为OFF。其它所有值均是非法的,并且对输出不起作用。
请求PDU说明了强制的线圈地址。从零开始寻址线圈。因此,寻址线圈1 为0。线圈值域的常量说明请求的ON/OFF 状态。十六进制值0XFF00请求线圈为ON。十六进制值0X0000请求线圈为
OFF。其它所有值均为非法的,并且对线圈不起作用。
正常响应是请求的应答,在写入线圈状态之后返回这个正常响应。

请求

功能码1个字节0x05
输出地址2个字节0x0000至0xFFFF
输出值2个字节0x0000至0xFF00?

响应

功能码1个字节0x05
输出地址2个字节0x0000至0xFFFF
输出值2个字节0x0000至0xFF00

错误

差错码1个字节0x85
异常码1个字节01或02或03或04

这是一个请求写线圈173为ON的实例:

请求响应
域名十六进制域名十六进制
功能05功能05
输出地址Hi00输出地址Hi00
输出地址LoAC输出地址LoAC
输出值Lo00输出值Lo00

3.6 06(0x06)功能码—写单个寄存器

在一个远程设备中,使用该功能码写单个保持寄存器。
请求PDU 说明了被写入寄存器的地址。从零开始寻址寄存器。因此,寻址寄存器1 为0。
正常响应是请求的应答,在写入寄存器内容之后返回这个正常响应。

请求

功能码1个字节0x06
寄存器地址2个字节0x0000至0xFFFF
寄存器值2个字节0x0000至0xFFFF

响应

功能码1个字节0x06
寄存器地址2个字节0x0000至0xFFFF
寄存器值N*x2个字节0x0000至0xFFFF

错误

差错码1个字节0x86
异常码1个字节01或02或03或04

这是一个请求将十六进制 00 03 写入寄存器2的实例:

请求响应
域名十六进制域名十六进制
功能06功能06
寄存器地址Hi00输出地址Hi00
寄存器地址Lo01输出地址Lo01
寄存器值Hi00输出值Hi00
寄存器值Lo03输出值Hi03

3.7 15(0x0F)功能码—写多个线圈

在一个远程设备中,使用该功能码强制线圈序列中的每个线圈为ON 或OFF。请求PDU说明了强制的线圈参考。从零开始寻址线圈。因此,寻址线圈1 为0。
请求数据域的内容说明了被请求的ON/OFF 状态。域比特位置中的逻辑“1”请求相应输出为ON。域比特位置中的逻辑“0”请求相应输出为OFF。
正常响应返回功能码、起始地址和强制的线圈数量。

请求PDU

功能码1个字节0x0F
起始地址2个字节0x0000至0xFFFF
输出数量2个字节0x0001至0x07B0
字节数1个字节N*
输出值N*X1个字节

注:*N=输出数量/8,如果余数不等于0,那么N=N+1

响应PDU

功能码1个字节0x0F
起始地址2个字节0x0000至0xFFFF
输出数量2个字节0x0001至0x07B0

错误

差错码1个字节0x8F
异常码1个字节01或02或03或04

这是一个请求从线圈20开始写入10个线圈的实例:

请求的数据内容为两个字节:十六进制CD 01 (二进制1100 1101 0000 0001)。使用下列方法,二进制比特对应输出。

比特1100110100000001
输出27262524232221202928

传输的第一字节(十六进制CD)寻址为输出27-20,在这种设置中,最低有效比特寻址为最低输出(20)。
传输的下一字节(十六进制01)寻址为输出29-28,在这种设置中,最低有效比特寻址为最低输出(28)。
应该用零填充最后数据字节中的未使用比特。

请求响应
域名十六进制域名十六进制
功能0F功能0F
起始地址Hi00起始地址Hi00
起始地址Lo13起始地址Lo13
输出数量Hi00输出数量Hi00
输出数量Lo0A输出数量Lo0A
字节数02
输出值HiCD
输出数量Lo01

3.8 16(0x10)功能码—写多个寄存器

在一个远程设备中,使用该功能码写连续寄存器块(1 至约120 个寄存器)。
在请求数据域中说明了请求写入的值。每个寄存器将数据分成两字节。
正常响应返回功能码、起始地址和被写入寄存器的数量。

请求

功能码1个字节0x10
起始地址2个字节0x0000至0xFFFF
寄存器数量2个字节0x0001至0x0078
字节数1个字节2xN*
寄存器值N*x2个字节

注:*N=寄存器的数量

响应

功能码1个字节0x04
起始地址2个字节0x0000至0xFFFF
寄存器数量2个字节1至123(0x7B)

错误

差错码1个字节0x90
异常码1个字节01或02或03或04

这是一个请求将十六进制00 0A 和01 02 写入以2 开始的两个寄存器的实例:

请求响应
域名十六进制域名十六进制
功能10功能10
起始地址Hi00起始地址Hi00
起始地址Lo01起始地址Lo01
寄存器数量Hi00寄存器数量Hi00
寄存器数量Lo02寄存器数量Lo02
字节数04
寄存器值Hi00
寄存器值Lo0A
寄存器值Hi01
寄存器值Lo02
  • 34
    点赞
  • 309
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答1: ucos-iii-tcpip.a是一个软件库,用于嵌入式系统中使用μC/OS-III操作系统和TCP/IP协议栈进行网络通信的开发。 ucos-iii-tcpip.a提供了一系列的接口和函数,帮助开发人员在嵌入式系统中实现TCP/IP网络通信功能。它包含了TCP/IP协议栈的实现以及与μC/OS-III操作系统的接口,使得开发人员可以简单地在嵌入式系统中实现TCP/IP网络通信功能。 使用ucos-iii-tcpip.a可以方便地创建网络任务,并通过接口函数来管理和控制网络通信。它提供了一些常用的网络协议,如TCP、UDP、IP等,并且支持网络连接、数据传输等基本的网络操作。此外,ucos-iii-tcpip.a还提供了一些高级功能,如网络管理、安全性、QoS等,以满足不同应用场景的需求。 通过使用ucos-iii-tcpip.a,嵌入式系统开发人员可以快速、简便地添加网络通信功能,提高系统的灵活性和可扩展性。它提供了一种可靠、高效的方式来实现嵌入式系统与外部设备之间的数据交换,使得嵌入式系统能够连接到互联网,实现远程控制、数据传输等功能。 总之,ucos-iii-tcpip.a是一款强大的软件库,它结合了μC/OS-III操作系统和TCP/IP协议栈,为嵌入式系统提供了完善的网络通信功能,帮助开发人员快速构建并实现网络连接和数据传输等功能,使得嵌入式系统能够更好地适应各种应用场景的需求。 ### 回答2: ucos-iii-tcpip.a是一个TCP/IP协议栈的静态库文件。uCos-III是一个开发嵌入式实时操作系统的工具。它提供了一种可靠的方法来构建实时系统,并可以方便地适应不同的硬件和应用需求。 ucos-iii-tcpip.a库是基于uCos-III实时操作系统的一个扩展库,用于支持TCP/IP协议栈的功能。TCP/IP协议栈是计算机网络通信的基础,它包括传输控制协议(TCP)和互联网协议(IP)。通过使用这个库,开发者可以轻松地在嵌入式系统中实现TCP/IP网络通信功能。 ucos-iii-tcpip.a库提供了一系列接口和函数,用于处理与TCP/IP协议相关的任务,如网络连接的建立和断开、数据传输的处理等。它还包含了各种网络协议的实现,如IP、TCP、UDP等,以及网络应用层协议的支持,如HTTP、FTP等。开发者可以通过调用这些函数和接口来完成各种网络通信任务。 使用ucos-iii-tcpip.a库可以极大地简化开发者在嵌入式系统中实现TCP/IP通信的工作量。它提供了一个高效可靠的通信框架,可以帮助开发者快速构建自己的网络应用。一旦完成了TCP/IP通信的底层实现,开发者可以更加专注于应用层的业务逻辑开发,而不需要过多关注网络通信的细节。 总结来说,ucos-iii-tcpip.a是一个用于嵌入式系统中支持TCP/IP协议栈的静态库文件,它提供了一系列接口和函数,帮助开发者实现TCP/IP网络通信功能。使用这个库可以简化开发工作,提高效率,同时为开发者提供了一个可靠的通信框架。 ### 回答3: ucos-iii-tcpip.a是一个软件库,主要用于嵌入式系统中实现TCP/IP网络协议栈。它基于Micrium公司开发的uC/OS-III实时操作系统,提供了一套完整的TCP/IP协议栈的实现。该软件库的目标是为嵌入式系统开发人员提供一个方便快捷且可靠的TCP/IP协议栈,使他们能够更容易地将网络功能集成到嵌入式应用中。 ucos-iii-tcpip.a具有多线程处理能力,能够同时处理多个网络连接和数据包,提供了 TCP、UDP、IP、ICMP等网络协议的实现。它支持IPv4和IPv6协议,可以实现IP地址的分配和路由功能,支持网络数据包的传输和接收,还提供了socket API接口供应用程序调用。 使用ucos-iii-tcpip.a,嵌入式系统开发人员可以方便地添加网络功能到他们的嵌入式应用中,无需从头开始开发TCP/IP协议栈,大大加快开发进度。在嵌入式系统中,网络功能往往是非常重要的,通过使用ucos-iii-tcpip.a,开发人员可以轻松实现远程控制、数据采集、与外部设备通信等功能。 总之,ucos-iii-tcpip.a是一个基于uC/OS-III实时操作系统的TCP/IP协议栈软件库,提供了完整的TCP/IP协议栈的实现,方便嵌入式系统开发人员快速添加网络功能到他们的应用中。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值