Modbus应用程序协议常用功能码详解 文章目录1 介绍1.1 本文件范围2 缩写3 背景3.1 MODBUS常用表述4 一般说明4.1 协议描述4.2 MBAP头部描述4.3 数据编码4.4 MODBUS数据模型4.4.1 MODBUS数据模型的应用示例4.5 MODBUS寻址模型4.6 定义 MODBUS 事务5 功能码类别5.1 公共功能码定义6 功能码描述6.1 读取线圈010x016.1.1 请求PDU6.1.2 响应PDU6.1.3 异常PDU6.1.4 读取线圈示例6.1.5 读线圈状态图6.2 写单个线圈 050x056.2.1 请求PDU6.2.2 响应PDU6.2.3 异常PDU6.2.4 写单个线圈示例6.2.5 写单个线圈状态图6.3 写多个线圈 150x0F6.3.1 请求PDU6.3.2 响应PDU6.3.3 异常PDU6.3.4 写多个线圈示例6.3.5 写多个线圈状态图6.4 读取离散输入 020x026.4.1 请求PDU6.4.2 响应PDU6.4.3 异常PDU6.4.4 读取离散输入示例6.4.5 读离散量输入状态图6.5 读取保持寄存器 030x036.5.1 请求PDU6.5.2 响应PDU6.5.3 异常PDU6.5.4 读保持寄存器示例6.5.5 读保持寄存器状态图6.6 写单个寄存器 060x066.6.1 请求PDU6.6.2 响应PDU6.6.3 异常PDU6.6.4 写单个寄存器示例6.6.5 写单个寄存器状态图6.7 写多个寄存器 160x106.7.1 请求PDU6.7.2 响应PDU6.7.3 异常PDU6.7.4 写多个保持寄存器示例6.7.5 写多个寄存器状态图6.8 读取输入寄存器 040x046.8.1 请求PDU6.8.2 响应PDU6.8.3 异常PDU6.8.4 读输入寄存器示例6.8.5 读输入寄存器状态图7 MODBUS异常响应7.1 MODBUS异常码1 介绍1.1 本文件范围MODBUS是一种应用层消息传递协议位于OSI模型的第7级它在不同类型的总线或网络上连接的设备之间提供客户端/服务器通信。MODBUS是一种请求/回复协议并提供由功能码指定的服务。MODBUS功能码是MODBUS请求/回复pdu的元素。本文档的目的是描述在MODBUS事务框架内使用的功能码。目前它使用以太网上的 TCP/IP。在各种媒体上进行的异步串行传输电线EIA/TIA-232-E、EIA-422、EIA/TIA-485-A光纤、无线电等。MODBUS一个高速令牌传递网络。2 缩写缩略语全称中文ADUApplication Data Unit应用数据单元HDLCHigh level Data Link Control高级数据链路控制HMIHuman Machine Interface人机界面IETFInternet Engineering Task Force互联网工程任务组I/OInput/Output输入/输出IPInternet Protocol互联网协议MACMedia Access Control媒体访问控制MBMODBUS ProtocolMODBUS协议MBAPMODBUS Application ProtocolMODBUS应用协议PDUProtocol Data Unit协议数据单元PLCProgrammable Logic Controller可编程逻辑控制器TCPTransmission Control Protocol传输控制协议CRCCyclic Redundancy Check循环冗余校验LSBLeast Significant Bit最低有效位MSBMost Significant Bit最高有效位MEIMODBUS Encapsulated InterfaceMODBUS封装接口3 背景MODBUS协议允许在所有类型的网络架构中进行轻松的通信。各种类型的设备(PLC、HMI、控制面板、驱动器、运动控制、I/O设备等)都可以使用MODBUS协议发起远程操作。相同的通信既可以在串行线路上完成也可以在以太网TCP/IP网络上完成允许使用MODBUS协议在多种类型的总线或网络之间进行通信。3.1 MODBUS常用表述行业规范标识标准官方术语英文标准名TCP网络通俗俗称Modbus主站主机MasterClient(客户端)上位机、主控、问询端Modbus从站从机SlaveServer(服务器)下位机、设备、应答端4 一般说明4.1 协议描述MODBUS 协议定义了一个独立于底层通信层的简单协议数据单元 (PDU)。 MODBUS 协议在特定总线或网络上的映射可以在应用数据单元ADU上引入一些附加字段。MODBUS应用数据单元由启动MODBUS事务的主机构建。功能码向从站指示要执行什么类型的操作。MODBUS应用程序协议建立了由主站发起的请求的格式。MODBUS协议数据单元的功能码字段以一个字节进行编码。有效代码的范围为1…255十进制保留的范围为128-255并用于异常响应。当消息从主机发送到从机设备时功能码字段会告诉从机要执行什么类型的操作。功能码“0”无效。子功能码被添加到一些功能码中以定义多个操作。从主机发送到从机的消息的数据字段包含从机用于执行功能码定义的操作的附加信息。可以包括线圈地址和寄存器地址、要处理的项目数量以及字段中实际数据字节数。在某些类型的请求中数据字段可能不存在零长度在这种情况下从机不需要任何附加信息。该功能码(比如0x07)单独指定了该操作。如果在正确接收的MODBUS ADU中所请求的MODBUS功能没有发生错误则由从机到主机的响应的数据字段包含所请求的数据。如果发生与所请求的MODBUS功能相关的错误则该数据字段将包含一个异常代码从机应用程序可以使用该异常代码来确定下一个要采取的操作。例如主机可以读取一组离散输出或输入的开/关状态也可以读取/写一组寄存器的数据内容。当从机响应主机时它将使用功能码字段来指示正常无错误响应或发生了某种错误称为异常响应。对于正常响应从机简单地向请求回显原始功能码。对于异常响应从机返回与请求PDU中的原始功能码相同的代码其最高有效位设置为逻辑1(0x80)。MODBUS PDU 的大小受限于最早串行 MODBUS 实现的大小约束最大 RS485 ADU 256 字节。MODBUS用于串行线通信的PDU256(字节) - 从机地址(1字节) - CRC(2字节)253字节。应用数据单元组成总字节数Modbus-RTU ADU从机地址(1字节)PDU(253字节)CRC(2字节)256字节Modbus-TCP ADUMBAP(7字节)PDU(253字节)260字节MODBUS协议定义了三个PDU。它们分别是MODBUS请求PDUmb_req_pdu对mb_req_pdu的定义为mb_req_pdu {function_code, request_data}function_code {1字节}MODBUS功能码request_data {n字节}这个字段依赖于功能码通常包含变量引用、变量计数、数据偏移量、子函数代码。MODBUS响应PDUmb_rsp_pdu对mb_rsp_pdu的定义为mb_rsp_pdu{function_coderesponse_data}function_code{1字节}MODBUS功能码response_data{n字节}这个字段依赖于功能码通常包含变量引用、变量计数、数据偏移量、子函数代码。MODBUS异常响应PDUmb_excep_rsp_pdu对mb_excep_rsp_pdu的定义为mb_excep_rsp_pdu{exception-function_coderequest_data}exception-function_code{1字节}MODBUS功能码0x80exception_code{1字节}MODBUS异常码。4.2 MBAP头部描述MBAP头部包含以下字段字段长度描述客户端服务器事务标识符2Byte标识一个 MODBUS 请求/响应事务。由客户端初始化由客户端初始化服务器从接收的请求中复制协议表示符2Byte0 MODBUS 协议由客户端初始化服务器从接收到的请求中复制长度2Byte后续字节数由客户端初始化(请求)由服务器初始化(响应)单元标识符1Byte标识连接在串行线或其他总线上的远程从站由客户端初始化服务器从接收到的请求中复制该头部共7字节长事务标识符用于事务配对MODBUS 服务器在响应中复制请求的事务标识符协议标识符用于系统内多路复用。MODBUS 协议由值 0 标识长度长度字段是后续字段的字节数包括单元标识符和数据字段单元标识符该字段用于系统内路由目的。它通常用于通过 Ethernet TCP/IP 网络与MODBUS 串行线之间的网关与 MODBUS 或 MODBUS 串行线从站进行通信。该字段由MODBUS 客户端在请求中设置服务器必须在响应中以相同的值返回。4.3 数据编码MODBUS对地址和数据项使用“大端”表示。这意味着当传输的数值大于一个字节时将首先发送最高的字节。例如4.4 MODBUS数据模型MODBUS的数据模型基于一系列具有显著特征的表。这四个主要表包括主要表对象类型访问类型说明线圈单个位读写此类数据可由应用程序修改离散量输入单个位只读此类数据可由I/O系统提供保持寄存器16位字读写此类数据可由应用程序修改输入寄存器16位字只读此类数据可由I/O系统提供输入与输出之间以及位寻址与字寻址数据项之间的区别并不暗示任何应用行为。将所有四个表视为彼此叠加是完全可接受的并且非常常见。对于每个主要表协议允许单独选择 65536 个数据项并且对这些项的读写操作设计为跨越多个连续数据项最大数据大小取决于事务功能码。显然通过 MODBUS 处理的所有数据位、寄存器必须位于设备应用程序内存中。但内存中的物理地址不应与数据引用混淆。唯一的要求是将数据引用与物理地址关联起来。MODBUS 逻辑引用号在 MODBUS 功能中使用是从零开始的无符号整数索引。4.4.1 MODBUS数据模型的应用示例下面的示例显示了组织设备中数据的两种方法。 可能存在不同的组织方法但本文档并未对所有组织方法进行描述。 每个设备都可以根据其应用程序拥有自己的数据组织。示例1具有4个独立数据块的设备下面的示例显示了具有数字和模拟、输入和输出的设备中的数据组织。每个块都是独立的因为来自不同块的数据没有相关性。因此每个块都可以使用不同的MODBUS协议函数进行访问。示例2只有一个数据块的设备在本例中该设备只有1个数据块。相同的数据可以通过几个MODBUS函数获得或通过16位访问或通过位访问。4.5 MODBUS寻址模型MODBUS应用程序协议精确地定义了PDU寻址规则。在 MODBUS PDU 中每个数据的寻址范围为 0 到 65535。它还清楚地定义了由 4 个块组成的 MODBUS 数据模型这些块包括从 1 到 n 编号的几个元素。在MODBUS数据模型中数据块中的每个元素的编号都从1到n。然后MODBUS数据模型必须绑定到设备应用程序。MODBUS 数据模型和设备应用程序之间的预映射完全是供应商设备特定的。MODBUS data model中是从1开始编号而MODBUS PDU addresses是从0开始编号。上图显示编号为 X 的 MODBUS 数据在 MODBUS PDUX-1中寻址。例如图中显示编号为1的Discrete Input的Modbus data数据在Modbus PDU的Read input 0中寻址。4.6 定义 MODBUS 事务以下状态图描述了在从机端对MODBUS事务的通用处理。一旦从机处理了请求就会使用适当的MODBUS从机事务构建MODBUS响应。根据处理的结果将构建两种类型的响应MODBUS正常响应响应功能码请求功能码MODBUS异常响应其目的是向主机提供在处理过程中检测到的错误的相关信息响应功能码请求功能码0x80提供了一个异常代码来指示错误的原因。5 功能码类别MODBUS功能代码有三类。它们是公共功能代码定义良好的功能码保证独一无二已由MODBUS.org社区进行验证公开记录的有可用的一致性测试包括已定义的公共分配功能码以及保留供将来使用的未分配功能码用户定义的功能码用户定义的功能码有两个范围即从65到72和从100到110的十进制。用户可以选择并实现该规范不支持的功能码。不能保证所选功能码的使用将是唯一的。如果用户希望将该功能重新定位为公共功能码他必须启动一个RFC来将更改引入公共类别并分配一个新的公共功能码。MODBUS组织公司明确保留开发拟议的RFC的权利。保留功能码一些公司目前用于遗留产品的功能代码但不供公众使用。参考性说明。5.1 公共功能码定义6 功能码描述6.1 读取线圈010x01此功能码用于读取远程设备中从1到2000个线圈的连续状态。请求PDU指定了起始地址即所指定的第一个线圈的地址以及线圈的数量。在PDU中线圈从零开始处理。因此编号为1-16的线圈被命名为0-15。响应消息中的线圈被打包为数据字段的每一位一个线圈。 状态表示为 1 ON 和 0 OFF。 第一个数据字节的 LSB 包含查询中寻址的线圈。 其他线圈跟随到该字节的高位端并在后续字节中从低位到高位。如果返回的线圈量不是8的倍数则最终数据字节中的其余位将用零填充高位补0。“字节计数”字段指定完整字节的数量。6.1.1 请求PDU字段长度范围功能码1Byte0x01起始地址2Byte0x0000 ~ 0xFFFF线圈数量2Byte1 ~ 2000(0x7D0)6.1.2 响应PDU字段长度范围功能码1Byte0x01字节数1ByteN*线圈状态nByten N 或 N1*N 输出的数量/8如果余数不为0则NN16.1.3 异常PDU字段长度范围错误码1Byte0x81功能码 0x80异常码1Byte01或02或03或046.1.4 读取线圈示例读取线圈20-38请求响应字段名(Hex)字段名(Hex)功能码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。 剩下的五个高位用零填充。6.1.5 读线圈状态图6.2 写单个线圈 050x05此功能码用于在远程设备中将单个输出写入 ON 或 OFF。请求 PDU 指定要强制的线圈的地址。 线圈从零开始寻址。 因此编号为 1 的线圈被寻址为 0。请求的 ON/OFF 状态由线圈值字段中的常量指定。 值 0XFF00 请求线圈开启。 值 0X0000 要求关闭线圈。 所有其他值都是非法的不会影响线圈。正常响应是请求的回显在写入线圈状态后返回。6.2.1 请求PDU字段长度范围功能码1Byte0x05线圈地址2Byte0x0000 ~ 0xFFFF线圈值2Byte0x0000 或 0xFF006.2.2 响应PDU字段长度范围功能码1Byte0x05线圈地址2Byte0x0000 ~ 0xFFFF线圈值2Byte0x0000 或 0xFF006.2.3 异常PDU字段长度范围错误码1Byte0x85功能码 0x80异常码1Byte01或02或03或046.2.4 写单个线圈示例以下是将线圈 173 写入 ON 的请求示例请求响应字段名(Hex)字段名(Hex)功能码05功能码05线圈地址Hi00线圈地址Hi00线圈地址LoAC线圈地址LoAC线圈值HiFF线圈值HiFF线圈值Lo00线圈值Lo006.2.5 写单个线圈状态图6.3 写多个线圈 150x0F该功能码用于在远程设备中强制线圈序列中的每个线圈打开或关闭。 请求 PDU 指定要强制的线圈参考。 线圈从零开始寻址。 因此编号为 1 的线圈寻址为 0。请求的开/关状态由请求数据字段的内容指定。字段位位置的逻辑“1”请求相应输出的ON。逻辑上的“0”请求其关闭。正常响应返回功能码、起始地址、强制线圈数量。6.3.1 请求PDU字段长度范围功能码1Byte0x0F起始地址2Byte0x0000 ~ 0xFFFF线圈数量2Byte0x0001 ~ 0x07B0字节计数1ByteN*线圈值N* × 1Byte*N 线圈数量/8如果余数不为0则N N16.3.2 响应PDU字段长度范围功能码1Byte0x0F起始地址2Byte0x0000 ~ 0xFFFF线圈数量2Byte0x0001 ~ 0x07B06.3.3 异常PDU字段长度范围错误码1Byte0x8F功能码 0x80异常码1Byte01或02或03或046.3.4 写多个线圈示例以下是从线圈 20 开始写入一系列 10 个线圈的请求示例请求响应字段名(Hex)字段名(Hex)功能码0F功能码0F起始地址Hi00起始地址Hi00起始地址Lo13起始地址Lo13线圈数量Hi00线圈数量Hi00线圈数量Lo0A线圈数量Lo0A字节计数02线圈值HiCD线圈值Lo01请求数据内容为两个字节CD 01 hex1100 1101 0000 0001 binary。 二进制位对应于以下方式的输出传输的第一个字节CD 十六进制寻址线圈 27-20最低有效位寻址该组中的最低线圈 (20)。传输的下一个字节01 十六进制寻址输出 29-28最低有效位寻址该组中的最低线圈 (28)。 最后一个数据字节中未使用的位应填零。6.3.5 写多个线圈状态图6.4 读取离散输入 020x02此功能代码用于读取远程设备中离散输入的1到2000个连续状态。请求PDU指定了起始地址即指定的第一个输入的地址以及输入的数量。在PDU中离散输入从零开始被寻址。因此编号为1-16的离散输入被处理为0-15。响应消息中的离散输入被打包为数据字段的每一位一个输入。 状态表示为 1ON 0 关闭。 第一个数据字节的 LSB 包含查询中寻址的输入。 其他输入跟随该字节的高位端并在后续字节中从低位到高位。如果返回的输入数量不是 8 的倍数则最终数据字节中的剩余位将用零填充朝向字节的高位方向。 字节计数字段指定完整数据字节的数量。6.4.1 请求PDU字段长度范围功能码1Byte0x02起始地址2Byte0x0000 ~ 0xFFFF离散量输入数量2Byte1 ~ 2000(0x7D0)6.4.2 响应PDU字段长度范围功能码1Byte0x02字节计数1ByteN*离散量输入状态N* × 1Byte*N 离散量输入状态的数量/8如果余数不为0则NN16.4.3 异常PDU字段长度范围错误码1Byte0x82功能码 0x80异常码1Byte01或02或03或046.4.4 读取离散输入示例读取离散量输入状态197-218请求响应字段名(Hex)字段名(Hex)功能码02功能码02起始地址Hi00字节计数03起始地址LoC4离散量输入状态204-197AC离散量输入数量00离散量输入状态212-205DB离散量输入数量16离散量输入状态218-21335离散输入 204–197 的状态显示为字节值 AC 十六进制即二进制1010 1100。输入 204 是该字节的 MSB输入 197 是 LSB。离散输入 218–213 的状态显示为字节值 35 十六进制即二进制0011 0101。输入 218 位于左起第三位位置输入 213 是 LSB。注意 剩余的两个位朝高位方向为零填充。6.4.5 读离散量输入状态图6.5 读取保持寄存器 030x03该功能码用于读取远程设备中连续的保持寄存器块的内容。 请求 PDU 指定起始寄存器地址和寄存器数量。 在 PDU 寄存器中从零开始寻址。 因此编号为 1-16 的寄存器被寻址为 0-15。6.5.1 请求PDU字段长度范围功能码1Byte0x03起始地址2Byte0x0000 ~ 0xFFFF寄存器数量2Byte1 ~ 125(0x7D)6.5.2 响应PDU响应消息中的寄存器数据被打包为每个寄存器两个字节每个字节内的二进制内容右对齐。对于每个寄存器第一个字节包含高位第二个字节包含低位。字段长度范围功能码1Byte0x03字节数1Byte2 × N*寄存器值N* × 2 Byte*N 寄存器数量6.5.3 异常PDU字段长度范围错误码1Byte0x83功能码 0x80异常码1Byte01或02或03或046.5.4 读保持寄存器示例以下是读取寄存器 108 – 110 的请求示例请求响应字段名(Hex)字段名(Hex)功能码03功能码03起始地址Hi00字节计数06起始地址Lo6B寄存器值Hi(108)02寄存器数量Hi00寄存器值Lo(108)2B寄存器数量Lo03寄存器值Hi(109)00寄存器值Lo(109)00寄存器值Hi(110)00寄存器值Lo(110)64寄存器 108 的内容显示为两个字节值 02 2B hex即 555 十进制。寄存器 109-110的内容分别为 00 00 和 00 64 hex即 0 和 100 十进制。6.5.5 读保持寄存器状态图6.6 写单个寄存器 060x06此功能代码用于在远程设备中写入单个保持寄存器。请求 PDU 指定要写入的寄存器的地址。 寄存器从零开始寻址。 因此编号为 1 的寄存器被寻址为 0。正常响应是请求的回显在写入寄存器内容后返回。6.6.1 请求PDU字段长度范围功能码1Byte0x06寄存器地址2Byte0x0000 ~ 0xFFFF寄存器值2Byte0x0000 ~ 0xFFFF6.6.2 响应PDU字段长度范围功能码1Byte0x06寄存器地址2Byte0x0000 ~ 0xFFFF寄存器值2Byte0x0000 ~ 0xFFFF6.6.3 异常PDU字段长度范围错误码1Byte0x86功能码 0x80异常码1Byte01或02或03或046.6.4 写单个寄存器示例以下是将寄存器 2 写入 0x0003的请求示例请求响应字段名(Hex)字段名(Hex)功能码06功能码06寄存器地址Hi00寄存器地址Hi00寄存器地址Lo01寄存器地址Lo01寄存器值Hi00寄存器值Hi00寄存器值Lo03寄存器值Lo036.6.5 写单个寄存器状态图6.7 写多个寄存器 160x10该功能码用于在远程设备中写入一块连续的寄存器1 到 123 个寄存器。请求的写入值在请求数据字段中指定。 数据被打包为每个寄存器的两个字节。正常响应返回功能码、起始地址和写入的寄存器数量。6.7.1 请求PDU字段长度范围功能码1Byte0x0F起始地址2Byte0x0000 ~ 0xFFFF寄存器数量2Byte0x0001 ~ 0x007B字节计数1Byte2 × N*寄存器值N* × 2Byte*N 寄存器数量6.7.2 响应PDU字段长度范围功能码1Byte0x0F起始地址2Byte0x0000 ~ 0xFFFF寄存器数量2Byte0x0001 ~ 0x7B6.7.3 异常PDU字段长度范围错误码1Byte0x90功能码 0x80异常码1Byte01或02或03或046.7.4 写多个保持寄存器示例这是一个请求写入两个寄存器的示例请求响应字段名(Hex)字段名(Hex)功能码10功能码10起始地址Hi00起始地址Hi00起始地址Lo01起始地址Lo01寄存器数量Hi00寄存器数量Hi00寄存器数量Lo02寄存器数量Lo02字节计数04寄存器值Hi00寄存器值Lo0A寄存器值Hi01寄存器值Lo026.7.5 写多个寄存器状态图6.8 读取输入寄存器 040x04该功能码用于读取远程设备中 1 到 125 个连续输入寄存器。 请求 PDU 指定起始寄存器地址和寄存器数量。 在 PDU 寄存器中从零开始寻址。 因此编号为 1-16 的输入寄存器寻址为 0-15。6.8.1 请求PDU字段长度范围功能码1Byte0x04起始地址2Byte0x0000 ~ 0xFFFF输入寄存器数量2Byte1 ~ 125(0x7D)6.8.2 响应PDU响应消息中的寄存器数据被打包为每个寄存器两个字节每个字节内的二进制内容右对齐。 对于每个寄存器第一个字节包含高位第二个字节包含低位。字段长度范围功能码1Byte0x04字节计数1Byte2 × N*输入寄存器值N* × 2 Byte*N 输入寄存器数量6.8.3 异常PDU字段长度范围错误码1Byte0x84功能码 0x80异常码1Byte01或02或03或046.8.4 读输入寄存器示例下面是一个要读取输入寄存器9的请求的示例请求响应字段名(Hex)字段名(Hex)功能码04功能码04起始地址Hi00字节计数02起始地址Lo08输入寄存器值Hi(9)00输入寄存器数量Hi00输入寄存器值Lo(9)0A输入寄存器数量Lo01输入寄存器 9 的内容显示为两个字节值 00 0A hex即 10 十进制。6.8.5 读输入寄存器状态图7 MODBUS异常响应当主机设备向从机设备发送请求时它期望得到正常响应。 主机的查询可能会发生四种可能的事件之一如果从机设备接收到的请求没有通信错误并且可以正常处理查询则返回正常响应。如果从机由于通信错误而没有收到请求则不返回任何响应。主机程序最终将处理该请求的超时条件。如果从机接收到请求但检测到通信错误(奇偶校验、LRC、CRC、……)则不返回任何响应。主机程序最终将处理该请求的超时条件。如果从机接收到的请求没有通信错误但不能处理它例如如果请求是读取一个不存在的线圈或寄存器从机将返回一个异常响应通知主机错误的性质。异常响应消息有两个字段可以将其与正常响应区分开来功能码字段在正常响应中从机在响应的功能码字段中回显原始请求的功能码。 所有功能代码的最高有效位 (MSB) 均为 0它们的值均低于 0x80。 在异常响应中从机将功能代码的 MSB 设置为 1。这使得异常响应中的功能码值比正常响应的值高 0x80。通过设置功能码的 MSB主机的应用程序可以识别异常响应并可以检查异常代码的数据字段。数据字段在正常响应中从机可能会返回数据字段中的数据或统计信息请求中请求的任何信息。 在异常响应中从机在数据字段中返回异常代码。 这定义了导致异常的从机条件。7.1 MODBUS异常码异常代码的列表异常码名称英文名称含义01非法功能码ILLEGAL FUNCTION查询中收到的功能代码不是从机允许的操作。 这可能是因为该功能代码仅适用于较新的设备并未在所选单元中实现。 它还可能表明从机处于错误状态无法处理这种类型的请求例如因为它未配置且被要求返回寄存器值。02非法数据地址ILLEGAL DATA ADDRESS查询中收到的数据地址不是从机允许的地址。 更具体地说参考号和传输长度的组合是无效的。 对于100个寄存器的控制器PDU将第一个寄存器寻址为0最后一个寄存器寻址为99。如果提交的请求起始寄存器地址为96寄存器数量为4则该请求将成功运行 地址至少在寄存器 96、97、98、99 上。如果提交的请求的起始寄存器地址为 96寄存器数量为 5则此请求将失败异常代码为 0x02“非法数据地址” 因为它试图对寄存器 96、97、98、99 和 100 进行操作并且没有地址为 100 的寄存器。03非法数据值ILLEGAL DATA VALUE数据字段中包含的值不是从机允许的值。 这表明复杂请求的其余部分的结构存在错误例如隐含长度不正确。 它具体并不意味着提交存储在寄存器中的数据项具有超出应用程序预期的值因为 MODBUS 协议不知道任何特定寄存器的任何特定值的重要性。04服务器设备故障SERVER DEVICE FAILURE当从机试图执行所请求的操作时发生了一个不可恢复的错误。05确认ACKNOWLEDGE专门与编程命令结合使用。 从机已接受请求并正在处理它但这样做需要很长时间。 返回此响应是为了防止主机发生超时错误。 主机接下来可以发出轮询程序完成消息以确定处理是否完成。06服务器设备繁忙SERVER DEVICE BUSY专门与编程命令结合使用。 从机正在处理一个长时间的程序命令。 主机应该稍后在从机空闲时重新传输消息。08存储器奇偶误差MEMORY PARITY ERROR专门与功能码 20 和 21 以及引用类型 6 结合使用以指示扩展文件区域未能通过一致性检查。 从机尝试读取记录文件但在内存中检测到奇偶校验错误。 主机可以重试请求但可能需要从机设备上的服务。0A网关路径不可用GATEWAY PATH UNAVAILABLE专门与网关结合使用表示网关无法分配从输入端口到输出端口的内部通信路径来处理请求。 通常意味着网关配置错误或过载。0B网关目标设备未能响应GATEWAY TARGET DEVICE FAILED TO RESPOND专门与网关结合使用表示未从目标设备获得响应。 通常意味着该设备不在网络上。