线圈与寄存器
线圈(Coils)
基本概念
线圈是一个布尔值(Boolean),通常表示0是关闭,1是开启,也可以理解为二进制状态(0或)。
线圈通常用于表示设备的开关状态,如启动/停止电机、打开/关闭阀门等。
读写特性
线圈既可以读取也可以写入。
读取线圈状态的功能码是01,写单个或多个线圈的功能码分别是05和15。
寄存器(Registers)
基本概念
寄存器是16位的整型数值(2字节),可以保存更复杂的数据,如传感器的读数、设置值等。
寄存器可以组合使用来存储更大的数据类型。
读写特性
Modbus寄存器根据读写特性和用途,主要分为保持寄存器(Holding Registers)和输入寄存器(Input Registers)。
保持寄存器:可读可写,用于存储可以被外部修改的数据,如设备控制和参数设定。
输入寄存器:只读,用于存储传感器或内部状态数据,如测量值或当前设备的状态。
读取保持寄存器的功能码是03,写单个或多个保持寄存器的功能码分别是06和16。
区别
数据类型:线圈是单个位(bit),寄存器是16位的整型数值。
用途:线圈主要用于控制输出设备,寄存器用于存储输入数据或配置设置。
读写特性:线圈既可以读取也可以写入,而输入寄存器是只读的(保持寄存器可读可写)
保持寄存器与输入寄存器
保持寄存器(Holding Register)和输入寄存器(Input Register)的主要区别在于读写权限、用途和功能码。
读写权限
- 保持寄存器:可读可写。这些寄存器用于存储设备的设置或控制参数,用户可以通过Modbus协议来读取或写入数据。
- 输入寄存器:只读。这些寄存器通常用于存储由外部设备(如传感器)提供的实时数据,数据是实时的但不能修改。
用途
- 保持寄存器:用于控制或设置设备的参数,如设定温度、控制阈值等。它们不仅支持读取,还可以写入,例如设置设备的工作参数。
- 输入寄存器:用于读取设备的实时测量数据,如温度、湿度、压力等传感器数据。这些数据不能被写入,只能用来读取外部设备提供的数据。
功能码
- 保持寄存器:读取通常使用功能码03(Read Holding Registers),写入通常使用功能码06(Write Single Register)或16(Write Multiple Registers)。
- 输入寄存器:读取通常使用功能码04(Read Input Registers)。
示例
- 保持寄存器:例如,设置温控设备的目标温度为25℃,这个目标温度会存储在保持型寄存器中,可以通过Modbus协议来修改。
- 输入寄存器:例如,读取一个温度传感器的实时温度,设备会通过输入型寄存器提供这个数据。
MODBUS POll使用
破解Key: 5A5742575C5D391A17627B6C010350
功能码说明
读取功能
读取功能返回的数据显示在网格窗口中。
01:读取线圈(0x)
02:读取离散量输入(1x)
03:读取保持寄存器(4x)
04:读取输入寄存器(3x)
写功能
写入功能写入显示在网格窗口上的数据。
05:写入单个线圈(写入线圈状态)
06:写入单个寄存器(写入保持寄存器)
15:写入多个线圈(写入线圈)
16:写入多个寄存器(写入保持寄存器)
功能码页面简介
Slave ID:配置从机地址
Function:配置寄存器/线圈类型
Address:配置读/写的寄存器/线圈起始地址
Quantity:配置读/写的寄存器/线圈个数
Scan Rate:读取数据周期,轮询发送,单位毫秒。
Disable:有两个勾选项,"Read/Write Disabled"可以选择是否禁止读写,"Disable on error"可以选择是否一出错就停止读写。
Rows:可以选择该窗口一列可以显示多少行,数字是对应的行数,最后一个选项"Fit to Quantity"是可以根据前面设置的"Quantity"数量自动匹配行数。
Hide Alias Columns:可以选择是否隐藏"Alias"列。
PLC Addresses(Base 1):可以选择通信的基地址是从0开始还是从1开始。
Address in Cell:是否在每个单元格中显示地址。
Enron/Daniel Mode:增加了浮点的数据类型扩展,读写一个寄存器是4个字节,主要用于跟支持该
调试简介
连接
F8可以调出功能码定义界面
下图用来说明读取保持寄存器的使用简介,其他读取方法如是
根据上面的配置生成RTU数据,点击应用即可完成发送
如果连接成功,配置好要测试的功能码后,可以通过display---->communication查看通信消息,
如果需要调试写入反馈,可以ALT+ T 调出调试中心,写入需要发送的数据,发送后,再在消息交互页面查看即可
应用实例
读取
这里我们以读取保持寄存器电压值为例(如上图)
功能码为03,配置如下,可见生成的RTU与文档给出的一致
C#代码如下:
ushort getVoltageAddr = 0x0040;
ushort quantity = 0x0002;
var result = modbusMaster?.ReadHoldingRegisters(slaveID, getVoltageAddr, quantity);
写入
这里以写入多个寄存器为例,如上图:
功能码为0x10,十进制为16
C# 代码为:
ushort setVoltageAddr = 0x0041;
ushort[] value = [0x00, (ushort)(current * 100)]; //0x0064
modbusMaster?.WriteMultipleRegisters((byte)slaveID, (ushort)setVoltageAddr, value);
这里需要注意两点:
1.modbus写入的数据为ushort(2个字节)
2.这里写入的数据为[0x00, (ushort)(current * 100)],需要读取的返回的值来判断
我这里读取的电压值时返回的数组长度为2,第一个的值为0(应该就是寄存器地址),第二个值为数据(电压值),所以这里写入的数组第一个也设置为0,第二个值为电压值