概述
在Modbus中,寄存器通常用于存储数据值,并可以通过不同的功能码来读取或写入这些值。Modbus 协议定义了几种不同的寄存器类型,每种类型都有其特定的用途。今天我们来详细介绍Modbus中常见的几种寄存器类型。
- 线圈和离散输入通常用于表示二进制的状态,如开/关状态。
- 保持寄存器和输入寄存器用于存储数值数据,如温度、压力等。
- 寄存器地址以16位无符号整数表示的,从0x0000 (0) 开始,最大到0xFFFF (65535)。
一、线圈 (Coils)
1.1用途
用于表示二进制的状态(逻辑状态),如开关或继电器的位置,如ON/OFF或TRUE/FALSE。
1.2功能码
01 (Read Coils,读取线圈状态) 、05 (Write Single Coil,写单个线圈)、15(Write Multiple Coils,同时写入多个线圈的状态)。只读和可写两种。
1.2.1详解
1.2.1.1读取线圈 (Coils)
功能码 01 (Read Coils)
- 请求:发送一个包含起始地址和数量的请求。
- 响应:接收一个包含线圈状态的数据包。
- 数据格式:状态通常以位的形式存储在一个字节中,每个位对应一个线圈的状态。
1.2.1.2写入单个线圈
功能码 05 (Write Single Coil)
- 请求:发送一个包含线圈地址和期望状态的请求。
- 响应:接收一个确认写入成功的响应。
- 数据格式:状态通常以位的形式发送,ON 为 1,OFF 为 0。
1.2.1.3写入多个线圈
功能码 15 (Write Multiple Coils)
- 请求:发送一个包含起始地址、数量和期望状态的数据包。
- 响应:接收一个确认写入成功的响应。
- 数据格式:状态通常以位的形式发送,每个位对应一个线圈的状态。
1.3地址范围
通常从0x0000 (0) 开始,最大到0xFFFF (65535),但在实际应用中,线圈的地址范围可能会受到设备的限制。
1.4示例
如果我们要读取设备上的第1个线圈的状态,我们可以按照以下步骤来读取:
- 选择功能码:使用功能码 01 (Read Coils)。
- 确定地址:线圈的起始地址为 0x0000 (0)。
- 发送请求:发送一个包含起始地址 0x0000 和数量 1 的请求。
- 接收响应:接收包含线圈状态的数据包。
- 解析响应:解析数据包中的位状态,确定线圈是否为 ON 或 OFF。
1.5注意事项
- 地址映射:明确设备的线圈地址映射,不同的设备有不同的地址分配。
- 兼容性:检查设备手册以及确认它支持的功能码。
- 错误处理:处理可能会出现的通信错误或设备错误响应。
二、离散输入 (Discrete Inputs)
2.1用途
读取设备的状态信息,用于表示只读的二进制状态信息,例如传感器的状态、开关位置或其他布尔类型的输入。
2.2功能码
02 (Read Discrete Inputs,读取离散输入状态),用于从设备读取离散输入的状态。
2.3地址范围
通常从0x0000 (0) 开始,最大到0xFFFF (65535)。每个离散输入对应一个位,通常按字节组织,即每个字节包含8个离散输入。
2.4存储
离散输入通常存储在设备内部的RAM中,只读,不能通过Modbus写入。
2.5读取操作
通过功能码02读取离散输入的状态,请求中包括起始地址和要读取的数量。
2.6响应格式
响应中包含一个字节数组,每个位代表一个离散输入的状态。第一位对应最低位 (LSB),第八位对应最高位 (MSB)。
2.7读取过程
- 构建请求:请求中包含功能码02、起始地址和数量。起始地址指明从哪个离散输入开始读取,数量指明要读取多少个离散输入。
- 发送请求:将请求通过Modbus串行链路或TCP/IP发送给设备。
- 接收响应:设备响应中包含一个字节数组,每个位代表一个离散输入的状态。响应中的字节数取决于请求的数量。
- 解析响应:解析响应中的字节数组,确定每个离散输入的状态。比如,如果响应中的第一个字节为0x05,那么第一位和第三位被设置为1,表示这两个离散输入处于开启状态。
2.8示例
如果我们要读取设备上第1到第8个离散输入的状态,则步骤如下:
2.8.1构建请求
- 功能码:02
- 起始地址:0x0000 (0)
- 数量:8
2.8.2发送请求
发送请求给设备。
2.8.3接收响应
如果设备响应为0x05,那第一位和第三位被设置为1。
2.8.4解析响应
- 0x05 的二进制表示为 00000101。
- 第一位和第三位被设置为1,表示第1个和第3个离散输入处于开启状态。
- 其他位为0,表示对应的离散输入处于关闭状态。
三、保持寄存器 (Holding Registers)
3.1用途
用于存储可读写的数值数据,如温度、压力或计数器值。
3.2功能码
03 (Read Holding Registers,读取保持寄存器) 、06 (Write Single Register,写单个保持寄存器)、16(Write Multiple Registers,写多个保持寄存器)。
3.2.1详解
3.2.1.1功能码:03,读取操作
请求格式:
- 地址:指定要读取的保持寄存器的起始地址
- 数量:指定要读取的保持寄存器的数量
响应格式:
- 数据:返回所请求的保持寄存器的值
3.2.1.2功能码:06,写单个保持寄存器
请求格式:
- 地址:指定要写入的保持寄存器的地址
- 值:要写入的值
响应格式:
- 确认:确认写入操作成功
3.2.1.3功能码:16,写多个保持寄存器
请求格式:
- 起始地址:指定要写入的保持寄存器的起始地址
- 数量:指定要写入的保持寄存器的数量
- 值:要写入的值的列表
响应格式:
- 确认:确认写入操作成功
3.3地址范围
通常从0x0000 (0) 开始,最大到0xFFFF (65535),共65536个。
3.4数据格式
- 整数 (Integers)
- 浮点数 (Floating Point Numbers)
- 字符串 (Strings)
- 结构化数据 (Structured Data)
3.5应用场景
- 配置参数:设备的配置参数,如PID控制器的设定值。
- 状态值:设备的状态值,如温度、压力等。
- 计数器:设备的计数器值,如操作次数等。
- 报警阈值:报警的阈值或触发条件。
- 统计信息:设备的工作时间或其他统计信息。
3.6示例
如果我们需要读取一个设备的温度值,该温度值存储在一个保持寄存器中,地址为0x0001,则:
3.6.1读取操作
功能码:03
请求格式:
- 地址:0x0001
- 数量:1
响应格式:
- 数据:返回0x0001寄存器中的温度值。
3.6.2写入操作
写单个保持寄存器:
功能码:06
请求格式:
- 地址:0x0001
- 值:新的温度值
响应格式:
- 确认:确认写入操作成功。
3.7注意事项
- 地址规划:合理规划保持寄存器的地址分配,避免地址冲突。
- 数据类型:确保读取或写入的数据类型与保持寄存器中存储的数据类型相匹配。
- 数据长度:注意保持寄存器中数据的长度,以确保正确解读数据。
四、输入寄存器 (Input Registers)
4.1用途
用于存储只读的数值数据,如模拟量输入(AI)或传感器的测量值。输入寄存器中的数据反映了设备的真实状态,通常由设备自动更新,而不是通过Modbus命令写入。
4.2功能码
04 (读取输入寄存器),只能通过读取操作来访问,不能直接写入。
4.2.1详解
4.2.1.1功能码
- 04 (读取输入寄存器)
4.2.1.2请求格式
- 设备地址:1字节,表示目标设备的地址。
- 功能码:1字节,值为04。
- 起始地址:2字节,表示要读取的第一个输入寄存器的地址。
- 寄存器数量:2字节,表示要读取的输入寄存器的数量。
4.2.1.3响应格式
- 设备地址:1字节,与请求中的相同。
- 功能码:1字节,值为04。
- 字节数:1字节,表示随后数据的字节数。
- 数据:2字节 * N,N为请求中指定的寄存器数量,表示读取的寄存器的值。
4.3地址范围
地址是16位无符号整数,通常从0x0000 (0) 开始,最大到0xFFFF (65535)。
4.4数据格式
通常存储16位的数值数据,如果需要存储更大的数值或浮点数,可以使用两个连续的输入寄存器来组合成一个32位的值。
4.5示例
如果我们想要读取设备上的温度值,该温度值存储在输入寄存器0x0001中,则:
4.5.1确定寄存器类型
温度值存储在输入寄存器 (Input Registers) 中
4.5.2选择功能码
使用功能码04 (读取输入寄存器)。
4.5.3指定地址
温度值所在的输入寄存器地址为0x0001。
4.5.4发送请求
- 设备地址:0x01
- 功能码:0x04
- 起始地址:0x0001
- 寄存器数量:0x0001
4.5.5接收响应
- 设备地址:0x01
- 功能码:0x04
- 字节数:0x02
- 数据:0xXXXX (实际温度值,以16位整数表示)
4.6注意事项
- 输入寄存器中的数据是由设备自动更新的,通常反映设备的实时状态。
- 输入寄存器只能通过读取操作访问,不能直接写入。
- 在实际应用中,设备会根据特定的协议配置来决定哪些寄存器用于存储输入数据。
五、举例说明
若我们想要读取设备上的温度值,则:
- 确定寄存器类型:通常使用保持寄存器 (Holding Registers) 或输入寄存器 (Input Registers) 存储温度值。
- 选择功能码:如果温度值存储在保持寄存器中,使用功能码03;如果存储在输入寄存器中,则使用功能码04。
- 指定地址:确定温度值所在的寄存器地址,例如0x0001。
- 发送请求:使用适当的Modbus功能码和地址发送读取请求。
- 接收响应:接收来自设备的响应,从中提取温度值。