2026/1/1 3:16:47
网站建设
项目流程
家具商务网站策划案,房地产信息网首页,万州建设工程信息网站,国际化网站Modbus 是一种串行通信协议#xff0c;最初由 Modicon#xff08;现为施耐德电气的一部分#xff09;为其可编程逻辑控制器 (PLC) 开发。它已成为工业自动化领域事实上的标准通信协议#xff0c;用于在主站设备#xff08;如监控计算机、HMI#xff09;和从站设备#x…Modbus 是一种串行通信协议最初由 Modicon现为施耐德电气的一部分为其可编程逻辑控制器 (PLC) 开发。它已成为工业自动化领域事实上的标准通信协议用于在主站设备如监控计算机、HMI和从站设备如 PLC、传感器、执行器之间交换数据。RTU (Remote Terminal Unit): 这是 Modbus 协议的一种传输模式。另一种常见模式是 ASCII。RTU 模式的主要特点是二进制编码: 数据以紧凑的二进制形式传输。高效: 相比 ASCII 模式RTU 模式传输相同信息量所需字节数更少效率更高。帧结构: 一个完整的 Modbus RTU 帧由以下部分组成从站地址(1 Byte): 标识目标从站设备。功能码(1 Byte): 指定主站请求的操作类型读、写和数据类型线圈、寄存器等。数据域(n Bytes): 包含请求或响应的具体数据地址、数量、值等。CRC 校验(2 Bytes): 循环冗余校验用于检测传输过程中可能出现的错误。时序: RTU 模式依靠字符间的时间间隔大于 3.5 个字符时间来界定帧的开始和结束。核心功能Modbus 协议的核心功能是让主站能够读取或写入从站设备中特定类型的数据存储区域。这些区域被抽象为四种主要类型线圈 (Coils): 1 位位输出量可读可写。通常对应 PLC 的数字量输出点 (DO)如继电器状态、灯的控制信号。功能码 01 (读), 05 (写单个), 15 (写多个)。离散量输入 (Discrete Inputs): 1 位位输入量只读。通常对应 PLC 的数字量输入点 (DI)如按钮、限位开关的状态。功能码 02 (读)。保持寄存器 (Holding Registers): 16 位字数据可读可写。通常用于存储模拟量数据如温度、压力、配置参数或计算结果。功能码 03 (读), 06 (写单个), 16 (写多个)。输入寄存器 (Input Registers): 16 位字数据只读。通常用于存储来自模拟量输入模块 (AI) 的数据。功能码 04 (读)。功能码解释功能码是 Modbus 帧中紧随从站地址之后的一个字节。它定义了主站请求的操作类型读/写以及要操作的数据类型线圈/离散输入/寄存器。下表列出了最常用的功能码功能码 (十六进制)功能码 (十进制)名称操作数据类型0x0101读线圈读线圈 (Coils)0x0202读离散量输入读离散输入 (DIs)0x0303读保持寄存器读保持寄存器 (HRs)0x0404读输入寄存器读输入寄存器 (IRs)0x0505写单个线圈写线圈 (Coils)0x0606写单个保持寄存器写保持寄存器 (HRs)0x0F15写多个线圈写线圈 (Coils)0x1016写多个保持寄存器写保持寄存器 (HRs)0x83131异常响应 (功能码 128)--异常响应: 如果从站无法执行主站的请求例如地址不存在、数据无效它会返回一个异常响应帧。该帧的功能码是原始功能码值 0x80或在原始功能码字节的最高位加 1。紧随功能码之后是一个异常码1 Byte用于指示具体的错误原因。常见的异常码有0x01: 非法功能 (不支持此功能码)0x02: 非法数据地址 (请求的地址无效或不存在)0x03: 非法数据值 (写入的值超出范围或无效)0x04: 从站设备故障 (设备内部错误)功能码 01 (0x01) 详解 - 读线圈功能: 读取一个或多个连续线圈 (1位输出量) 的当前状态 (ON/OFF, 1/0)。请求帧结构:[从站地址](1 Byte)[功能码 0x01](1 Byte)[起始地址高字节](1 Byte) - 要读取的第一个线圈的地址的高8位。[起始地址低字节](1 Byte) - 要读取的第一个线圈的地址的低8位。[线圈数量高字节](1 Byte) - 要读取的线圈总数的高8位。[线圈数量低字节](1 Byte) - 要读取的线圈总数的低8位。[CRC16 低字节](1 Byte)[CRC16 高字节](1 Byte)响应帧结构:[从站地址](1 Byte)[功能码 0x01](1 Byte)[字节数](1 Byte) - 后面数据域包含的字节数。计算公式(线圈数量 7) / 8。[数据域](n Bytes) - 线圈状态按位打包的结果。每个字节包含8个线圈的状态LSB 表示第一个线圈MSB 表示该字节内的最后一个线圈。如果读取的线圈数量不是8的倍数最后一个字节的高位用0填充。[CRC16 低字节](1 Byte)[CRC16 高字节](1 Byte)功能码 01 示例场景: 主站 (地址 0x01) 请求读取从站 (地址 0x02) 的线圈起始地址为 0x0000 (线圈0)读取 10 个线圈 (线圈0 - 线圈9)。假设线圈状态线圈0ON(1), 线圈1OFF(0), 线圈2ON(1), 线圈3ON(1), 线圈4OFF(0), 线圈5OFF(0), 线圈6ON(1), 线圈7OFF(0), 线圈8ON(1), 线圈9OFF(0)。主站请求帧 (Hex):02 01 00 00 00 0A CRC02: 从站地址 (0x02)01: 功能码 (读线圈)00 00: 起始地址 0x0000 (线圈0)00 0A: 线圈数量 0x000A (10个)CRC: 校验码 (假设计算为C10C)从站响应帧 (Hex):02 01 02 CD 01 CRC02: 从站地址 (0x02)01: 功能码 (读线圈)02: 字节数 2 Bytes (因为 (10 7) / 8 1.25 - 向上取整为 2)CD: 第一个数据字节 (0xCD 二进制1100 1101)LSB (Bit0) 1(线圈0 ON)Bit1 0(线圈1 OFF)Bit2 1(线圈2 ON)Bit3 1(线圈3 ON)Bit4 0(线圈4 OFF)Bit5 0(线圈5 OFF)Bit6 1(线圈6 ON)MSB (Bit7) 1(线圈7 ON? 但假设是OFF这里有问题后面解释)01: 第二个数据字节 (0x01 二进制0000 0001)LSB (Bit0) 1(线圈8 ON)Bit1 0(线圈9 OFF)Bits 2-7: 未使用填充为0 (读取10个线圈第二个字节只用低2位)注意: 第一个字节0xCD(1100 1101) 中MSB (Bit7) 对应线圈7。在我们的假设状态中线圈7是 OFF(0)所以 Bit7 应该是0。但是0xCD的 Bit7 是1(因为0xCD1100 1101)。这里存在一个错误假设。修正假设状态线圈7ON(1)。那么线圈0ON(1), 1OFF(0), 2ON(1), 3ON(1), 4OFF(0), 5OFF(0), 6ON(1), 7ON(1) - 第一个字节1100 11010xCD(LSB 是线圈0)。线圈8ON(1), 9OFF(0) - 第二个字节0000 00010x01(LSB 是线圈8)。CRC: 校验码 (假设计算为E40B)功能码 03 (0x03) 详解 - 读保持寄存器功能: 读取一个或多个连续保持寄存器 (16位数据) 的当前值。请求帧结构:[从站地址](1 Byte)[功能码 0x03](1 Byte)[起始地址高字节](1 Byte) - 要读取的第一个寄存器的地址的高8位。[起始地址低字节](1 Byte) - 要读取的第一个寄存器的地址的低8位。[寄存器数量高字节](1 Byte) - 要读取的寄存器总数的高8位。[寄存器数量低字节](1 Byte) - 要读取的寄存器总数的低8位。[CRC16 低字节](1 Byte)[CRC16 高字节](1 Byte)响应帧结构:[从站地址](1 Byte)[功能码 0x03](1 Byte)[字节数](1 Byte) - 后面数据域包含的字节数。计算公式寄存器数量 * 2(因为每个寄存器16位2字节)。[数据域](n Bytes) - 寄存器的值按顺序排列。每个寄存器占用2个字节通常是大端序 (Big-Endian)即高字节在前 (MSB)低字节在后 (LSB)。例如寄存器值 0x1234 会表示为12 34。[CRC16 低字节](1 Byte)[CRC16 高字节](1 Byte)功能码 03 示例场景: 主站 (地址 0x01) 请求读取从站 (地址 0x03) 的保持寄存器起始地址为 0x0006 (寄存器6)读取 3 个寄存器 (寄存器6, 7, 8)。假设寄存器值寄存器6: 0x1234 (4660)寄存器7: 0x5678 (22136)寄存器8: 0x9ABC (39612)主站请求帧 (Hex):03 03 00 06 00 03 CRC03: 从站地址 (0x03)03: 功能码 (读保持寄存器)00 06: 起始地址 0x0006 (寄存器6)00 03: 寄存器数量 0x0003 (3个)CRC: 校验码 (假设计算为45F1)从站响应帧 (Hex):03 03 06 12 34 56 78 9A BC CRC03: 从站地址 (0x03)03: 功能码 (读保持寄存器)06: 字节数 6 Bytes (3 寄存器 * 2 字节/寄存器)12 34: 寄存器6 的值 (0x1234)56 78: 寄存器7 的值 (0x5678)9A BC: 寄存器8 的值 (0x9ABC)CRC: 校验码 (假设计算为05D9)重要注意事项地址偏移: Modbus 协议定义的数据区地址是从 0 开始的。但很多设备文档或软件 (如 SCADA, HMI) 可能会使用基于 1 的索引例如线圈1对应地址0x0000。务必查看设备手册确认其寻址方式。字节顺序 (Endianness): 对于16位寄存器Modbus 协议规定传输时是大端序。但在将两个字节组合成一个16位整数时或在表示更大数据类型如32位浮点数占用两个寄存器时应用层必须定义寄存器之间的组合顺序是[RegA Hi, RegA Lo]还是[RegA Lo, RegA Hi]以及多寄存器数据类型的字节顺序。这是应用中常见的混淆点。数据类型映射: 保持寄存器中存储的原始字节数据需要映射到具体的物理意义如温度、压力。这通常需要知道缩放比例、偏移量和数据类型整数、浮点数。CRC 计算: CRC 校验是保证通信可靠性的重要环节。计算算法是标准的 Modbus RTU CRC16 (多项式 0x8005初始值 0xFFFF)。通信两端必须使用相同的算法。调试工具: 使用串口监视工具或专门的 Modbus 调试工具如 Modscan, QModMaster可以直观地查看发送和接收的原始报文是排查通信问题的有效手段。注意查看十六进制文本。