
public class ModbusBase
{
public List<byte> GetReadCommand(byte deviceAddr, byte funcCode, ushort startAddr, ushort length)
{
List<byte> buffer = new List<byte>();
buffer.Add(deviceAddr);
buffer.Add(funcCode);
buffer.Add(BitConverter.GetBytes(startAddr)[1]);
buffer.Add(BitConverter.GetBytes(startAddr)[0]);
buffer.Add(BitConverter.GetBytes(length)[1]);
buffer.Add(BitConverter.GetBytes(length)[0]);
return buffer;
}
}
public class SerialPortBase : ModbusBase
{
}
public class ModbusRTU : SerialPortBase
{
SerialPort serialPort = null;
public ModbusRTU(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits)
{
serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
}
public bool Open()
{
try
{
if (serialPort == null)
throw new Exception();
if (!serialPort.IsOpen)
serialPort.Open();
return true;
}
catch
{
return false;
}
}
public bool Close()
{
try
{
if (serialPort != null && serialPort.IsOpen)
serialPort.Close();
serialPort = null;
return true;
}
catch
{
return false;
}
}
public List<ushort> ReadKeepRegister(byte deviceAddr, byte funcCode, ushort startAddr, ushort length)
{
List<byte> bytes = this.GetReadCommand(deviceAddr, funcCode, startAddr, length);
bytes.AddRange(CRC16(bytes));
if (serialPort.IsOpen)
{
serialPort.Write(bytes.ToArray(), 0, bytes.Count);
int time = 1;
while (time < 2000 && serialPort.BytesToRead <= 0)
{
time += 1;
Thread.Sleep(1);
}
if (serialPort.BytesToRead <= 0)
throw new Exception("响应超时");
byte[] buffer = new byte[serialPort.BytesToRead];
serialPort.Read(buffer, 0, buffer.Length);
List<byte> byteList = new List<byte>(buffer);
List<byte> checkCRC = byteList.GetRange(byteList.Count - 2, 2);
byteList.RemoveRange(byteList.Count - 2, 2);
List<byte> validCode = CRC16(byteList);
if (validCode.SequenceEqual(checkCRC))
{
int fc = byteList[1];
if ((fc & 0x80) == 0x80)
{
throw new Exception(byteList[2].ToString());
}
byteList.RemoveRange(0, 3);
List<ushort> values = new List<ushort>();
List<byte> valueBytes = new List<byte>();
for (int i = 0; i < length; i++)
{
valueBytes.Clear();
valueBytes.Add(byteList[i * 2 + 1]);
valueBytes.Add(byteList[i * 2]);
var value = BitConverter.ToUInt16(valueBytes.ToArray(), 0);
values.Add(value);
}
return values;
}
}
else
{
Task.Run(async () =>
{
while (true)
{
await Task.Delay(2000);
if (serialPort.IsOpen)
{
Console.WriteLine("连接正常");
continue;
}
try
{
Console.WriteLine("连接断开,尝试重新连接");
serialPort.Open();
}
catch (System.IO.IOException ex)
{
Console.WriteLine("设备连接断开");
continue;
}
}
});
}
return null;
}
public List<float> ReadKeepRegisterFloat(byte deviceAddr, byte funcCode, ushort startAddr, ushort length)
{
List<byte> bytes = this.GetReadCommand(deviceAddr, funcCode, startAddr, length);
bytes.AddRange(CRC16(bytes));
if (serialPort.IsOpen)
{
serialPort.Write(bytes.ToArray(), 0, bytes.Count);
int time = 1;
while (time < 2000 && serialPort.BytesToRead <= 0)
{
time += 1;
Thread.Sleep(1);
}
if (serialPort.BytesToRead <= 0)
throw new Exception("响应超时");
byte[] buffer = new byte[serialPort.BytesToRead];
serialPort.Read(buffer, 0, buffer.Length);
List<byte> byteList = new List<byte>(buffer);
List<byte> checkCRC = byteList.GetRange(byteList.Count - 2, 2);
byteList.RemoveRange(byteList.Count - 2, 2);
List<byte> validCode = CRC16(byteList);
if (validCode.SequenceEqual(checkCRC))
{
int fc = byteList[1];
if ((fc & 0x80) == 0x80)
{
throw new Exception(byteList[2].ToString());
}
byteList.RemoveRange(0, 3);
List<float> values = new List<float>();
List<byte> valueBytes = new List<byte>();
for (int i = 0; i < length / 2; i++)
{
valueBytes.Clear();
valueBytes.Add(byteList[i * 4 + 3]);
valueBytes.Add(byteList[i * 4 + 2]);
valueBytes.Add(byteList[i * 4 + 1]);
valueBytes.Add(byteList[i * 4]);
var value = BitConverter.ToSingle(valueBytes.ToArray(), 0);
values.Add(value);
}
return values;
}
}
else
{
Task.Run(async () =>
{
while (true)
{
await Task.Delay(2000);
if (serialPort.IsOpen)
{
Console.WriteLine("连接正常");
continue;
}
try
{
Console.WriteLine("连接断开,尝试重新连接");
serialPort.Open();
}
catch (System.IO.IOException ex)
{
Console.WriteLine("设备连接断开");
continue;
}
}
});
}
return null;
}
private List<byte> CRC16(List<byte> value)
{
ushort poly = 0xA001;
ushort crcInit = 0xFFFF;
if (value == null || !value.Any())
throw new ArgumentException("");
ushort crc = crcInit;
for (int i = 0; i < value.Count; i++)
{
crc = (ushort)(crc ^ (value[i]));
for (int j = 0; j < 8; j++)
{
crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ poly) : (ushort)(crc >> 1);
}
}
byte hi = (byte)((crc & 0xFF00) >> 8);
byte lo = (byte)(crc & 0x00FF);
List<byte> buffer = new List<byte>();
buffer.Add(lo);
buffer.Add(hi);
return buffer;
}
}