这里讲解modbusRTU和modbusTCP。
先安装NModbus库,在nuget中搜索:
直接上代码!!!
public abstract class BaseModbus
{
/// <summary>
/// 关闭
/// </summary>
public abstract void Close();
}
public enum FunctionCode
{
/// <summary>
/// 01读取单个线圈
/// </summary>
ReadCoils,
/// <summary>
/// 02读取输入线圈/离散量线圈
/// </summary>
ReadInputs,
/// <summary>
/// 03读取保持寄存器
/// </summary>
ReadHoldingRegisters,
/// <summary>
/// 04读取输入寄存器
/// </summary>
ReadInputRegisters,
/// <summary>
/// 05写单个线圈
/// </summary>
WriteSingleCoilAsync,
/// <summary>
/// 06写单个输入线圈/离散量线圈/单个寄存器
/// </summary>
WriteSingleRegisterAsync,
/// <summary>
/// 0x0F写多个线圈 0x0F=15
/// </summary>
WriteMultipleCoilsAsync,
/// <summary>
/// 0x10写多个保持寄存器 0x10=16
/// </summary>
WriteMultipleRegistersAsync
}
RTU
public class ModbusRTU : BaseModbus
{
public bool IsConnection = false;
/// <summary>
/// 串口操作对象
/// </summary>
public SerialPort? SPort;
public IModbusSerialMaster? rtuMaster;
/// <summary>
/// RTU连接
/// </summary>
/// <param name="PortName"></param>
/// <param name="BaudRate">波特率</param>
/// <param name="DataBits">数据位</param>
/// <param name="StopBits">停止位</param>
/// <param name="Parity">校验位</param>
/// <param name="WriteTimeout"></param>
/// <param name="ReadTimeout"></param>
/// <returns></returns>
public virtual bool Connection(string PortName, int BaudRate, int DataBits,
System.IO.Ports.StopBits StopBits, System.IO.Ports.Parity Parity, int WriteTimeout = 200, int ReadTimeout = 200)
{
try
{
SPort = new SerialPort();
SPort.PortName = PortName;
SPort.BaudRate = BaudRate;
SPort.DataBits = DataBits;
SPort.Parity = Parity;
SPort.StopBits = StopBits;
SPort.WriteTimeout = WriteTimeout;
SPort.ReadTimeout = ReadTimeout;
SPort.Open();
//SPort.DataReceived += SPort_DataReceived;
var factory = new ModbusFactory();
rtuMaster = factory.CreateRtuMaster(SPort);
IsConnection = true;
return true;
}
catch (Exception)
{
IsConnection = false;
return false;
}
}
/// <summary>
/// 关闭
/// </summary>
public override void Close()
{
if (SPort == null)
return;
SPort.Close();
IsConnection = false;
}
/// <summary>
/// 写入
/// </summary>
/// <param name="functionCode">功能码类型</param>
/// <param name="slaveAddress">站地址</param>
/// <param name="startAddress">位置,从0开始</param>
/// <param name="coilsBuffer">线圈数据</param>
/// <param name="registerBuffer">寄存器数据</param>
public virtual async void WriteData(FunctionCode functionCode, byte slaveAddress, ushort startAddress, bool[]? coilsBuffer = null, ushort[]? registerBuffer = null)
{
try
{
if (SPort == null)
return;
if (SPort.IsOpen == false)
{
SPort.Open();
}
switch (functionCode)
{
case FunctionCode.WriteSingleCoilAsync:
if (coilsBuffer == null)
return;
await rtuMaster.WriteSingleCoilAsync(slaveAddress, startAddress, coilsBuffer[0]);
break;
case FunctionCode.WriteSingleRegisterAsync:
if (registerBuffer == null)
return;
await rtuMaster.WriteSingleRegisterAsync(slaveAddress, startAddress, registerBuffer[0]);
break;
case FunctionCode.WriteMultipleCoilsAsync:
if (coilsBuffer == null)
return;
await rtuMaster.WriteMultipleCoilsAsync(slaveAddress, startAddress, coilsBuffer);
break;
case FunctionCode.WriteMultipleRegistersAsync:
if (registerBuffer == null)
return;
await rtuMaster.WriteMultipleRegistersAsync(slaveAddress, startAddress, registerBuffer);
break;
default:
break;
}
}
catch (Exception)
{
}
}
/// <summary>
/// 读取
/// </summary>
/// <param name="functionCode">功能码类型</param>
/// <param name="slaveAddress">站地址</param>
/// <param name="startAddress">位置,从0开始</param>
/// <param name="numberOfPoints">长度</param>
public virtual (bool[]?, ushort[]?) ReadData(FunctionCode functionCode, byte slaveAddress, ushort startAddress, ushort numberOfPoints)
{
bool[]? coilsBuffer = null;//线圈数据
ushort[]? registerBuffer = null;//寄存器数据
try
{
if (rtuMaster == null)
return (coilsBuffer, registerBuffer);
if (SPort == null)
return (coilsBuffer, registerBuffer);
if (SPort.IsOpen == false)
{
SPort.Open();
}
switch (functionCode)
{
case FunctionCode.ReadCoils:
coilsBuffer = rtuMaster.ReadCoils(slaveAddress, startAddress, numberOfPoints);
break;
case FunctionCode.ReadHoldingRegisters:
registerBuffer = rtuMaster.ReadHoldingRegisters(slaveAddress, startAddress, numberOfPoints);
break;
case FunctionCode.ReadInputs:
coilsBuffer = rtuMaster.ReadInputs(slaveAddress, startAddress, numberOfPoints);
break;
case FunctionCode.ReadInputRegisters:
registerBuffer = rtuMaster.ReadInputRegisters(slaveAddress, startAddress, numberOfPoints);
break;
default:
break;
}
return (coilsBuffer, registerBuffer);
}
catch (Exception)
{
}
return (coilsBuffer, registerBuffer);
}
}
TCP
public class ModbusTCP : BaseModbus
{
/// <summary>
/// 网口操作对象
/// </summary>
public TcpClient? tcpClient;
public IModbusMaster? tcpMaster;
public bool IsConnection;
/// <summary>
/// TCP连接
/// </summary>
/// <param name="ip"></param>
/// <param name="point"></param>
/// <returns></returns>
public virtual bool Connection(string ip, int port=-1)
{
try
{
if (string.IsNullOrWhiteSpace(ip) || port<0)
return false;
tcpClient = new TcpClient();
tcpClient.Connect(IPAddress.Parse(ip), port);
var factory = new ModbusFactory();
tcpMaster = factory.CreateMaster(tcpClient);
IsConnection = true;
return true;
}
catch (Exception)
{
IsConnection = false;
return false;
}
}
/// <summary>
/// 关闭
/// </summary>
public override void Close()
{
if (tcpClient == null)
return;
tcpClient.Close();
IsConnection = false;
}
/// <summary>
/// 写入
/// </summary>
/// <param name="functionCode">功能码类型</param>
/// <param name="slaveAddress">站地址</param>
/// <param name="startAddress">位置,从0开始</param>
/// <param name="coilsBuffer">线圈数据</param>
/// <param name="registerBuffer">寄存器数据</param>
public virtual async void WriteData(FunctionCode functionCode, byte slaveAddress, ushort startAddress, bool[]? coilsBuffer = null, ushort[]? registerBuffer = null)
{
try
{
if (tcpClient == null)
return;
if (tcpMaster == null)
return;
switch (functionCode)
{
case FunctionCode.WriteSingleCoilAsync:
if (coilsBuffer == null)
return;
await tcpMaster.WriteSingleCoilAsync(slaveAddress, startAddress, coilsBuffer[0]);
break;
case FunctionCode.WriteSingleRegisterAsync:
if (registerBuffer == null)
return;
await tcpMaster.WriteSingleRegisterAsync(slaveAddress, startAddress, registerBuffer[0]);
break;
case FunctionCode.WriteMultipleCoilsAsync:
if (coilsBuffer == null)
return;
await tcpMaster.WriteMultipleCoilsAsync(slaveAddress, startAddress, coilsBuffer);
break;
case FunctionCode.WriteMultipleRegistersAsync:
if (registerBuffer == null)
return;
await tcpMaster.WriteMultipleRegistersAsync(slaveAddress, startAddress, registerBuffer);
break;
default:
break;
}
}
catch (Exception)
{
}
}
/// <summary>
/// 读取
/// </summary>
/// <param name="functionCode">功能码类型</param>
/// <param name="slaveAddress">站地址</param>
/// <param name="startAddress">位置,从0开始</param>
/// <param name="numberOfPoints">长度</param>
public virtual (bool[]?, ushort[]?) ReadData(FunctionCode functionCode, byte slaveAddress, ushort startAddress, ushort numberOfPoints)
{
bool[]? coilsBuffer = null;//线圈数据
ushort[]? registerBuffer = null;//寄存器数据
try
{
if (tcpMaster == null)
return (coilsBuffer, registerBuffer);
switch (functionCode)
{
case FunctionCode.ReadCoils:
coilsBuffer = tcpMaster.ReadCoils(slaveAddress, startAddress, numberOfPoints);
break;
case FunctionCode.ReadHoldingRegisters:
registerBuffer = tcpMaster.ReadHoldingRegisters(slaveAddress, startAddress, numberOfPoints);
break;
case FunctionCode.ReadInputs:
coilsBuffer = coilsBuffer = tcpMaster.ReadInputs(slaveAddress, startAddress, numberOfPoints);
break;
case FunctionCode.ReadInputRegisters:
registerBuffer = tcpMaster.ReadInputRegisters(slaveAddress, startAddress, numberOfPoints);
break;
default:
break;
}
return (coilsBuffer, registerBuffer);
}
catch (Exception)
{
}
return (coilsBuffer, registerBuffer);
}
}
C#技术交流QQ群:371769310