Browse Source

fix modbus driver

pull/15/head
Gavin 9 years ago
parent
commit
588337ff3b
  1. 92
      SCADA/Program/ModbusDriver/ModbusRTUDriver.cs
  2. 22
      SCADA/Program/ModbusDriver/ModbusTCPDriver.cs
  3. BIN
      SCADA/dll/ModbusDriver.dll

92
SCADA/Program/ModbusDriver/ModbusRTUDriver.cs

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

22
SCADA/Program/ModbusDriver/ModbusTCPDriver.cs

@ -32,7 +32,14 @@ namespace ModbusDriver
DeviceAddress dv = DeviceAddress.Empty; DeviceAddress dv = DeviceAddress.Empty;
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(address))
return dv; return dv;
dv.Area = _slaveId; 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]) switch (address[0])
{ {
case '0': case '0':
@ -145,16 +152,6 @@ namespace ModbusDriver
set { _timeout = value; } set { _timeout = value; }
} }
byte _slaveId;//设备ID 单元号 字节号
/// <summary>
/// 设备ID 单元号 字节号
/// </summary>
public byte SlaveId
{
get { return _slaveId; }
set { _slaveId = value; }
}
List<IGroup> _grps = new List<IGroup>(20); List<IGroup> _grps = new List<IGroup>(20);
public IEnumerable<IGroup> Groups public IEnumerable<IGroup> Groups
{ {
@ -167,14 +164,13 @@ namespace ModbusDriver
get { return _server; } get { return _server; }
} }
public ModbusTCPReader(IDataServer server, short id, string name, string ip, int timeOut = 500, string spare1 = "0", string spare2 = null) public ModbusTCPReader(IDataServer server, short id, string name, string ip, int timeOut = 500, string spare1 = null, string spare2 = null)
{ {
_id = id; _id = id;
_name = name; _name = name;
_server = server; _server = server;
_ip = ip; _ip = ip;
_timeout = timeOut; _timeout = timeOut;
if (!string.IsNullOrEmpty(spare1)) byte.TryParse(spare1, out _slaveId);
} }
public bool Connect() public bool Connect()

BIN
SCADA/dll/ModbusDriver.dll

Binary file not shown.
Loading…
Cancel
Save