|
|
|
@ -1,11 +1,10 @@ |
|
|
|
using System; |
|
|
|
using DataService; |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.ComponentModel; |
|
|
|
using System.IO; |
|
|
|
using System.IO.Ports; |
|
|
|
using System.Text; |
|
|
|
using System.Timers; |
|
|
|
using DataService; |
|
|
|
|
|
|
|
namespace ModbusDriver |
|
|
|
{ |
|
|
|
@ -111,8 +110,8 @@ namespace ModbusDriver |
|
|
|
_serialPort.DataBits = 8; |
|
|
|
_serialPort.Parity = Parity.Even; |
|
|
|
_serialPort.StopBits = StopBits.One; |
|
|
|
if (!string.IsNullOrEmpty(spare1)) byte.TryParse(spare1, out _slaveId); |
|
|
|
} |
|
|
|
|
|
|
|
private SerialPort _serialPort; |
|
|
|
|
|
|
|
/* |
|
|
|
@ -125,10 +124,10 @@ namespace ModbusDriver |
|
|
|
Long:代表有符号的64位整数,范围从-9223372036854775808 ~ 9223372036854775808 |
|
|
|
Ulong:代表无符号的64位整数,范围从0 ~ 18446744073709551615。 |
|
|
|
*/ |
|
|
|
private byte[] CreateReadHeader(int startAddress, ushort length, byte function) |
|
|
|
private byte[] CreateReadHeader(int id, int startAddress, ushort length, byte function) |
|
|
|
{ |
|
|
|
byte[] data = new byte[8]; |
|
|
|
data[0] = _slaveId; // Slave id high byte 从站地址
|
|
|
|
data[0] = (byte)id; // Slave id high byte 从站地址
|
|
|
|
data[1] = function; // Message size
|
|
|
|
byte[] _adr = BitConverter.GetBytes((short)startAddress);//以字节数组的形式返回指定的 16 位无符号整数值。
|
|
|
|
//apply on small endian, TODO:support big endian
|
|
|
|
@ -145,10 +144,10 @@ namespace ModbusDriver |
|
|
|
} |
|
|
|
|
|
|
|
#region 写单个线圈或单个离散输出 功能码:0x05
|
|
|
|
public byte[] WriteSingleCoils(int startAddress, bool OnOff) |
|
|
|
public byte[] WriteSingleCoils(int id, int startAddress, bool OnOff) |
|
|
|
{ |
|
|
|
byte[] data = new byte[8]; |
|
|
|
data[0] = _slaveId; // Slave id high byte
|
|
|
|
data[0] = (byte)id; // Slave id high byte
|
|
|
|
data[1] = Modbus.fctWriteSingleCoil; // Function code
|
|
|
|
byte[] _adr = BitConverter.GetBytes((short)startAddress); |
|
|
|
data[2] = _adr[1]; // Start address
|
|
|
|
@ -162,11 +161,11 @@ namespace ModbusDriver |
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region 写多个线圈 功能码:0x0F 15
|
|
|
|
public byte[] WriteMultipleCoils(int startAddress, ushort numBits, byte[] values) |
|
|
|
public byte[] WriteMultipleCoils(int id, int startAddress, ushort numBits, byte[] values) |
|
|
|
{ |
|
|
|
int len = values.Length; |
|
|
|
byte[] data = new byte[len + 9]; |
|
|
|
data[0] = _slaveId; // Slave id high byte 从站地址高八位
|
|
|
|
data[0] = (byte)id; // Slave id high byte 从站地址高八位
|
|
|
|
data[1] = Modbus.fctWriteMultipleCoils; // Function code 功能码
|
|
|
|
byte[] _adr = BitConverter.GetBytes((short)startAddress); |
|
|
|
data[2] = _adr[1]; // Start address 开始地址高八位
|
|
|
|
@ -184,10 +183,10 @@ namespace ModbusDriver |
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region 写单个保持寄存器 功能码:0x06
|
|
|
|
public byte[] WriteSingleRegister(int startAddress, byte[] values) |
|
|
|
public byte[] WriteSingleRegister(int id, int startAddress, byte[] values) |
|
|
|
{ |
|
|
|
byte[] data = new byte[8]; |
|
|
|
data[0] = _slaveId; // Slave id high byte 从站地址高八位
|
|
|
|
data[0] = (byte)id; // Slave id high byte 从站地址高八位
|
|
|
|
data[1] = Modbus.fctWriteSingleRegister; // Function code 功能码
|
|
|
|
byte[] _adr = BitConverter.GetBytes((short)startAddress); |
|
|
|
data[2] = _adr[1]; // Start address 开始地址高八位
|
|
|
|
@ -202,12 +201,12 @@ namespace ModbusDriver |
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region 写多个保持寄存器 功能码:0x10 16
|
|
|
|
public byte[] WriteMultipleRegister(int startAddress, byte[] values) |
|
|
|
public byte[] WriteMultipleRegister(int id, int startAddress, byte[] values) |
|
|
|
{ |
|
|
|
int len = values.Length; |
|
|
|
if (len % 2 > 0) len++; |
|
|
|
byte[] data = new byte[len + 9]; |
|
|
|
data[0] = _slaveId; // Slave id high byte 从站地址
|
|
|
|
data[0] = (byte)id; // Slave id high byte 从站地址
|
|
|
|
data[1] = Modbus.fctWriteMultipleRegister; // Function code 功能码
|
|
|
|
byte[] _adr = BitConverter.GetBytes((short)startAddress); |
|
|
|
data[2] = _adr[1]; // Start address 开始地址高八位
|
|
|
|
@ -237,47 +236,47 @@ namespace ModbusDriver |
|
|
|
get { return 0xFD; } //0xFD 十进制为253
|
|
|
|
} |
|
|
|
|
|
|
|
byte _slaveId;//设备ID 单元号 字节号
|
|
|
|
/// <summary>
|
|
|
|
/// 设备ID 单元号 字节号
|
|
|
|
/// </summary>
|
|
|
|
public byte SlaveId |
|
|
|
{ |
|
|
|
get { return _slaveId; } |
|
|
|
set { _slaveId = value; } |
|
|
|
} |
|
|
|
|
|
|
|
public DeviceAddress GetDeviceAddress(string address) |
|
|
|
{ |
|
|
|
DeviceAddress dv = DeviceAddress.Empty; |
|
|
|
if (string.IsNullOrEmpty(address)) |
|
|
|
return dv; |
|
|
|
var sindex = address.IndexOf(':'); |
|
|
|
if (sindex > 0) |
|
|
|
{ |
|
|
|
int slaveId; |
|
|
|
if (int.TryParse(address.Substring(0, sindex), out slaveId)) |
|
|
|
dv.Area = slaveId; |
|
|
|
address = address.Substring(sindex + 1); |
|
|
|
} |
|
|
|
switch (address[0]) |
|
|
|
{ |
|
|
|
case '0': |
|
|
|
{ |
|
|
|
dv.Area = Modbus.fctReadCoil; |
|
|
|
dv.DBNumber = Modbus.fctReadCoil; |
|
|
|
int st; |
|
|
|
int.TryParse(address, out st); |
|
|
|
dv.Bit = (byte)(st % 16); |
|
|
|
st /= 16; |
|
|
|
dv.Start = st; |
|
|
|
dv.Bit--; |
|
|
|
} |
|
|
|
break; |
|
|
|
case '1': |
|
|
|
{ |
|
|
|
dv.Area = Modbus.fctReadDiscreteInputs; |
|
|
|
dv.DBNumber = Modbus.fctReadDiscreteInputs; |
|
|
|
int st; |
|
|
|
int.TryParse(address.Substring(1), out st); |
|
|
|
dv.Bit = (byte)(st % 16); |
|
|
|
st /= 16; |
|
|
|
dv.Start = st; |
|
|
|
dv.Bit--; |
|
|
|
} |
|
|
|
break; |
|
|
|
case '4': |
|
|
|
{ |
|
|
|
int index = address.IndexOf('.'); |
|
|
|
dv.Area = Modbus.fctReadHoldingRegister; |
|
|
|
dv.DBNumber = Modbus.fctReadHoldingRegister; |
|
|
|
if (index > 0) |
|
|
|
{ |
|
|
|
dv.Start = int.Parse(address.Substring(1, index - 1)); |
|
|
|
@ -286,12 +285,14 @@ namespace ModbusDriver |
|
|
|
else |
|
|
|
dv.Start = int.Parse(address.Substring(1)); |
|
|
|
dv.Start--; |
|
|
|
dv.Bit--; |
|
|
|
dv.ByteOrder = ByteOrder.Network; |
|
|
|
} |
|
|
|
break; |
|
|
|
case '3': |
|
|
|
{ |
|
|
|
int index = address.IndexOf('.'); |
|
|
|
dv.Area = Modbus.fctReadInputRegister; |
|
|
|
dv.DBNumber = Modbus.fctReadInputRegister; |
|
|
|
if (index > 0) |
|
|
|
{ |
|
|
|
dv.Start = int.Parse(address.Substring(1, index - 1)); |
|
|
|
@ -300,10 +301,11 @@ namespace ModbusDriver |
|
|
|
else |
|
|
|
dv.Start = int.Parse(address.Substring(1)); |
|
|
|
dv.Start--; |
|
|
|
dv.Bit--; |
|
|
|
dv.ByteOrder = ByteOrder.Network; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
dv.Bit--; |
|
|
|
return dv; |
|
|
|
} |
|
|
|
|
|
|
|
@ -317,11 +319,11 @@ namespace ModbusDriver |
|
|
|
object _async = new object(); |
|
|
|
public byte[] ReadBytes(DeviceAddress address, ushort size) |
|
|
|
{ |
|
|
|
int area = address.Area; |
|
|
|
var func = (byte)address.DBNumber; |
|
|
|
try |
|
|
|
{ |
|
|
|
byte[] header = area == Modbus.fctReadCoil ? CreateReadHeader(address.Start * 16, (ushort)(16 * size), (byte)area) : |
|
|
|
CreateReadHeader(address.Start, size, (byte)area); |
|
|
|
byte[] header = func < 3 ? CreateReadHeader(address.Area, address.Start * 16, (ushort)(16 * size), func) : |
|
|
|
CreateReadHeader(address.Area, address.Start, size, func); |
|
|
|
_serialPort.Write(header, 0, header.Length); |
|
|
|
byte[] frameBytes = new byte[size * 2 + 5]; |
|
|
|
byte[] data = new byte[size * 2]; |
|
|
|
@ -330,7 +332,7 @@ namespace ModbusDriver |
|
|
|
{ |
|
|
|
while (numBytesRead != frameBytes.Length) |
|
|
|
numBytesRead += _serialPort.Read(frameBytes, numBytesRead, frameBytes.Length - numBytesRead); |
|
|
|
if (frameBytes[0] == _slaveId && Utility.CheckSumCRC(frameBytes)) |
|
|
|
if (frameBytes[0] == func && Utility.CheckSumCRC(frameBytes)) |
|
|
|
{ |
|
|
|
Array.Copy(frameBytes, 3, data, 0, data.Length); |
|
|
|
return data; |
|
|
|
@ -348,14 +350,14 @@ namespace ModbusDriver |
|
|
|
|
|
|
|
public ItemData<int> ReadInt32(DeviceAddress address) |
|
|
|
{ |
|
|
|
byte[] bit = ReadBytes(address, 4); |
|
|
|
byte[] bit = ReadBytes(address, 2); |
|
|
|
return bit == null ? new ItemData<int>(0, 0, QUALITIES.QUALITY_BAD) : |
|
|
|
new ItemData<int>(BitConverter.ToInt32(bit, 0), 0, QUALITIES.QUALITY_GOOD); |
|
|
|
} |
|
|
|
|
|
|
|
public ItemData<uint> ReadUInt32(DeviceAddress address) |
|
|
|
{ |
|
|
|
byte[] bit = ReadBytes(address, 4); |
|
|
|
byte[] bit = ReadBytes(address, 2); |
|
|
|
return bit == null ? new ItemData<uint>(0, 0, QUALITIES.QUALITY_BAD) : |
|
|
|
new ItemData<uint>(BitConverter.ToUInt32(bit, 0), 0, QUALITIES.QUALITY_GOOD); |
|
|
|
} |
|
|
|
@ -409,7 +411,7 @@ namespace ModbusDriver |
|
|
|
|
|
|
|
public int WriteBytes(DeviceAddress address, byte[] bit) |
|
|
|
{ |
|
|
|
var data = WriteMultipleRegister(address.Start, bit); |
|
|
|
var data = WriteMultipleRegister(address.Area, address.Start, bit); |
|
|
|
_serialPort.Write(data, 0, data.Length); |
|
|
|
_serialPort.ReadByte(); |
|
|
|
var chr = _serialPort.ReadByte(); |
|
|
|
@ -418,7 +420,7 @@ namespace ModbusDriver |
|
|
|
|
|
|
|
public int WriteBit(DeviceAddress address, bool bit) |
|
|
|
{ |
|
|
|
var data = WriteSingleCoils(address.Start + address.Bit, bit); |
|
|
|
var data = WriteSingleCoils(address.Area, address.Start + address.Bit, bit); |
|
|
|
_serialPort.Write(data, 0, data.Length); |
|
|
|
_serialPort.ReadByte(); |
|
|
|
var chr = _serialPort.ReadByte(); |
|
|
|
@ -427,7 +429,7 @@ namespace ModbusDriver |
|
|
|
|
|
|
|
public int WriteBits(DeviceAddress address, byte bits) |
|
|
|
{ |
|
|
|
var data = WriteSingleRegister(address.Start, new byte[] { bits }); |
|
|
|
var data = WriteSingleRegister(address.Area, address.Start, new byte[] { bits }); |
|
|
|
_serialPort.Write(data, 0, data.Length); |
|
|
|
_serialPort.ReadByte(); |
|
|
|
var chr = _serialPort.ReadByte(); |
|
|
|
@ -436,7 +438,7 @@ namespace ModbusDriver |
|
|
|
|
|
|
|
public int WriteInt16(DeviceAddress address, short value) |
|
|
|
{ |
|
|
|
var data = WriteSingleRegister(address.Start, BitConverter.GetBytes(value)); |
|
|
|
var data = WriteSingleRegister(address.Area, address.Start, BitConverter.GetBytes(value)); |
|
|
|
_serialPort.Write(data, 0, data.Length); |
|
|
|
var chr = _serialPort.ReadByte(); |
|
|
|
return (chr & 0x80) > 0 ? -1 : 0; |
|
|
|
@ -444,7 +446,7 @@ namespace ModbusDriver |
|
|
|
|
|
|
|
public int WriteUInt16(DeviceAddress address, ushort value) |
|
|
|
{ |
|
|
|
var data = WriteSingleRegister(address.Start, BitConverter.GetBytes(value)); |
|
|
|
var data = WriteSingleRegister(address.Area, address.Start, BitConverter.GetBytes(value)); |
|
|
|
_serialPort.Write(data, 0, data.Length); |
|
|
|
var chr = _serialPort.ReadByte(); |
|
|
|
return (chr & 0x80) > 0 ? -1 : 0; |
|
|
|
@ -452,7 +454,7 @@ namespace ModbusDriver |
|
|
|
|
|
|
|
public int WriteUInt32(DeviceAddress address, uint value) |
|
|
|
{ |
|
|
|
var data = WriteMultipleRegister(address.Start, BitConverter.GetBytes(value)); |
|
|
|
var data = WriteMultipleRegister(address.Area, address.Start, BitConverter.GetBytes(value)); |
|
|
|
_serialPort.Write(data, 0, data.Length); |
|
|
|
_serialPort.ReadByte(); |
|
|
|
var chr = _serialPort.ReadByte(); |
|
|
|
@ -461,7 +463,7 @@ namespace ModbusDriver |
|
|
|
|
|
|
|
public int WriteInt32(DeviceAddress address, int value) |
|
|
|
{ |
|
|
|
var data = WriteMultipleRegister(address.Start, BitConverter.GetBytes(value)); |
|
|
|
var data = WriteMultipleRegister(address.Area, address.Start, BitConverter.GetBytes(value)); |
|
|
|
_serialPort.Write(data, 0, data.Length); |
|
|
|
_serialPort.ReadByte(); |
|
|
|
var chr = _serialPort.ReadByte(); |
|
|
|
@ -470,7 +472,7 @@ namespace ModbusDriver |
|
|
|
|
|
|
|
public int WriteFloat(DeviceAddress address, float value) |
|
|
|
{ |
|
|
|
var data = WriteMultipleRegister(address.Start, BitConverter.GetBytes(value)); |
|
|
|
var data = WriteMultipleRegister(address.Area, address.Start, BitConverter.GetBytes(value)); |
|
|
|
_serialPort.Write(data, 0, data.Length); |
|
|
|
_serialPort.ReadByte(); |
|
|
|
var chr = _serialPort.ReadByte(); |
|
|
|
@ -479,11 +481,11 @@ namespace ModbusDriver |
|
|
|
|
|
|
|
public int WriteString(DeviceAddress address, string str) |
|
|
|
{ |
|
|
|
var data = WriteMultipleRegister(address.Start, Encoding.ASCII.GetBytes(str)); |
|
|
|
var data = WriteMultipleRegister(address.Area, address.Start, Encoding.ASCII.GetBytes(str)); |
|
|
|
_serialPort.Write(data, 0, data.Length); |
|
|
|
_serialPort.ReadByte(); |
|
|
|
var chr = _serialPort.ReadByte(); |
|
|
|
return chr == _slaveId ? -1 : 0; |
|
|
|
return chr == address.DBNumber ? -1 : 0; |
|
|
|
} |
|
|
|
|
|
|
|
public int WriteValue(DeviceAddress address, object value) |
|
|
|
|