Modbus是一个免费的协议,协议设计简单,有很多成熟的库支持。比如C#版本的NModubs4就很好,入门简单,使用方便。
首先,在工程中使用NuGet添加NModbus4的包。
在使用文件中,添加引用。不同的接口模式,引用对象不同,Modbus Slave TCP模型需要以下几项:
using System.Net;
using System.Net.Sockets;
using Modbus.Data;
using Modbus.Device;
初始化大概有几个步骤:创建TCP Listener对象、创建ModbusTcpSalve对象、启动侦听服务。
TcpListener listener = new TcpListener(IPAddress.Parse("0.0.0.0"), 502);
listener.Start();
ModbusTcpSlave modbusSlave = ModbusTcpSlave.CreateTcp(1, listener);
//创建寄存器存储对象
modbusSlave.DataStore = DataStoreFactory.CreateDefaultDataStore();
Modbus有个DataStore对象,用来存储数据,对应的状态的地址如下:
//01 Coil Status, Addr: 00001
ModbusDataCollection<bool> coilDiscretes = modbusSlave.DataStore.InputDiscretes;
//02 Input Status, Addr: 10001
ModbusDataCollection<bool> inputDiscretes = modbusSlave.DataStore.CoilDiscretes;
//03 Holding Register, Addr: 40001
ModbusDataCollection<ushort> holdingRegisters = modbusSlave.DataStore.HoldingRegisters;
//04 Input Register, Addr: 30001
ModbusDataCollection<ushort> InputRegisters = modbusSlave.DataStore.InputRegisters;
定义之后,就可以直接通过这些对象读写数据了。
NModbus4库已经封装了对于TCP访问数据的封装,服务端只需要维护数据更新即可。
受Modbus协议限制,HoldingRegisters和InputRegisters每个地址仅16位2个字节长度。当实际数据值超过2个字节时,需要占用多个地址空间。比如int32,float都需要4个字节,两个地址。这些数据怎么存放,高低位怎么对齐,就产生了所谓的ABCD、CDAB等转换,这个Master与Slave一致就可以。
Int32等类型数据更新时,需要同时对多个存储地址进行更新,而master可能还在高速并发读数据,需要注意使用一个同步锁,避免数据更新一半就被读取,产生数据不一致问题。文章来源:https://www.toymoban.com/news/detail-532825.html
//将float类型分解成两个ushort类型
public void SetValue32(ModbusDataCollection<ushort>data,int offset, float value)
{
lock (modbusSlave.DataStore.SyncRoot)
{
data[offset] = BitConverter.ToUInt16(BitConverter.GetBytes(value), 0);
data[offset + 1] = BitConverter.ToUInt16(BitConverter.GetBytes(value), 2);
}
}
//将int32类型分解成两个ushort类型
public void SetValue32(ModbusDataCollection<ushort> data, int offset, Int32 value)
{
lock (modbusSlave.DataStore.SyncRoot)
{
data[offset] = BitConverter.ToUInt16(BitConverter.GetBytes(value), 0);
data[offset + 1] = BitConverter.ToUInt16(BitConverter.GetBytes(value), 2);
}
}
Modbus对于字符串,并没有明确约定。推进使用Unicode编码,首先是与OPC的默认字符串编码格式一致,其次的每个中英文都占用一个地址2个字节,方便计算长度。文章来源地址https://www.toymoban.com/news/detail-532825.html
public void SetValueString(ModbusDataCollection<ushort> data, int offset, string value)
{
const int maxStringLen = 20;
lock (modbusSlave.DataStore.SyncRoot)
{
byte[] dst = new byte[appConfigModbus.StringLen * 2];
byte[] bb = Encoding.Unicode.GetBytes(value);
for (int i = 0; i < bb.Length && i < dst.Length; i++)
{
dst[i] = bb[i];
}
for (int i = 0; i < maxStringLen; i += 2)
{
data[offset + i / 2] = BitConverter.ToUInt16(dst, i);
}
}
}
到了这里,关于C#使用NModbus4读写Modbus数据的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!