全文字数1796 | 阅读需要3分钟
4. 开源类库NModbus4
Modbus协议的应用层实际上是对底层实际发送数据格式进行了编码,可以看到的是底层实际发送数据格式还是字节类型,只要了解每个字节代表含义就可以完成解码,得到想要的数据。本小节中我们将会介绍使用开源类库NModbus4来轻松完成Modbus应用层的工作。NModBus4项目的GitHub地址为https://github.com/NModbus4/NModbus4,支持TCP、UDP、RTU等Modbus协议,可用于对Modbus从设备的连接和通信。
先简单介绍一下NModbus4类库中的几个重要方法,如表4所示。
表4 NModbus4类的方法
利用这些方法就完成对Modbus所有的应用层操作,实现完整的Modbus协议层编写,而不需要管物理层的事情,包括读取/写入线圈,读取/写入寄存器等等。接下来我们来看两个具体的实例,一个基于串口,另外一个基于TCP。
基于串口的Modbus实现
在《C#与开源虚拟仪器技术》书的实例13.3.4_1中我们编写了一个基于串口的Modbus程序,基本上集成了Modbus常用的功能,界面如图7所示。
图7 串口Modbus程序界面
为了验证Modbus程序的功能,可以安装Modbus Slave这款测试Modbus协议的软件,它可以仿真从站设备。图8中我们配置了Modbus串口信息,包括波特率校验位等。
图8 在Modbus Slave中配置Modbus串口信息
图9对从站功能进行配置,配置位开启保持寄存器(4XXXX),寄存器可读可写。
图9 在Modbus Slave中配置从站功能
打开实例程序,配置好串口选项,和Modbus Slave保持一致,然后打开串口。在功能码中选择“10H-写入多个保持寄存器”,从站号1,起始地址0,输入需要写入数据用空格隔开。点击执行按钮Read/Write后,可以在Modbus Slave看到这几个地址的寄存器已经被修改了,如图10所示。
图10 写入数据到多个寄存器
在功能码中选择“03H-读取多个保持寄存器”,从站号1,起始地址0,读取长度为5。点击执行按钮Read/Write后,可以在demo程序中看到已经将这几个数据读取出来了,如图11所示。
图11 从多个保持寄存器中读取数据
基于TCP的Modbus实现
在《C#与开源虚拟仪器技术》书中的实例13.3.4_2是基于TCP的Modbus协议实现,同样也集成了Modbus常用的功能。界面如图12所示。
图12 TCP Modbus程序界面
由于每个从站设备都相当于服务器,所以要首先配置好从站设备,在连接建立上选择TCP/IP模式,并且设置空闲端口号,如图13所示。
图13 在Modbus Slave中配置Modbus TCP/IP信息
然后配置从站功能,当前配置位开启保持寄存器(4XXXX),寄存器可读可写功能。打开实例程序,IP地址选择127.0.0.1,这地址本机的IP回环地址,同时选择端口号为502,点击开始按钮。在功能码中选择“10H-写入多个保持寄存器”,从站号1,起始地址0,输入需要写入数据用空格隔开。点击执行按钮Read/Write后,可以在Modbus Slave看到这几个地址的寄存器已经被修改了,如图14所示。
图14 写入数据到多个寄存器
在功能码中选择“03H-读取多个保持寄存器”,从站号1,起始地址0,读取长度为5。点击执行按钮Read/Write后,可以在demo程序中看到已经将这几个数据读取出来了,如图15所示。
图15 从多个保持寄存器中读取数据
之前只介绍了利用NModbus4类库做为Master的方法,实际利用这个类库也可以作为Slave,这样可以将运行程序的设备(工控机)也作为节点一部分,方便与其他系统进行网络(低速的)互联,特别是可以方便其他设备对应用程序进行控制和观察特征数值等等操作。
范例如图16所示,分为Slave端和Master端,首先填入设备的监听IP,这边填写的是127.0.0.1就是监听本机,如果可以监听任意IP建议修改成为listener = new TcpListener(IPAddress.Any, 502);
这里唯一需要理解的是:
slave.DataStore = DataStoreFactory.CreateDefaultDataStore(); //创建寄存器存储对象
这就是创建,Modbus协议中的65536个元素的地址空间。查看DataStore的定义,分别定义了四种寄存器,正好对应Modbus的四种寄存器类型。
同时可以建立事件:
slave.ModbusSlaveRequestReceived += new EventHandler((obj, o) =>
{
MessageBox.Show("ModbusSlaveRequestReceived:"+ ((IModbusMessage)o.Message).FunctionCode.ToString());
});
有助于快速了解Master端的数据写入,通过FunctionCode枚举查找是进行的哪个寄存器进行的操作,是包括保持寄存器和线圈两种,因为只有这两种寄存器是允许写入的。这样就可以通过事件,处理Master端的操作请求(遍历对应寄存器)。
图16
需要注意的是,除去线圈寄存器外其他寄存器都是16位,所以如果需要表达float类型的数据需要进行数据处理,然后分别以高低位的形式写入到两个寄存器中,同时读取也需要从两个寄存器读取后组合。
相关阅读