From 588337ff3b45036a641ea9b21c856b241e0ee259 Mon Sep 17 00:00:00 2001 From: Gavin Date: Wed, 20 Dec 2017 09:38:49 +0800 Subject: [PATCH] fix modbus driver --- SCADA/Program/ModbusDriver/ModbusRTUDriver.cs | 92 +++++++++--------- SCADA/Program/ModbusDriver/ModbusTCPDriver.cs | 22 ++--- SCADA/dll/ModbusDriver.dll | Bin 22528 -> 22016 bytes 3 files changed, 56 insertions(+), 58 deletions(-) diff --git a/SCADA/Program/ModbusDriver/ModbusRTUDriver.cs b/SCADA/Program/ModbusDriver/ModbusRTUDriver.cs index 637ac97..b69532f 100644 --- a/SCADA/Program/ModbusDriver/ModbusRTUDriver.cs +++ b/SCADA/Program/ModbusDriver/ModbusRTUDriver.cs @@ -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 单元号 字节号 - /// - /// 设备ID 单元号 字节号 - /// - 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 ReadInt32(DeviceAddress address) { - byte[] bit = ReadBytes(address, 4); + byte[] bit = ReadBytes(address, 2); return bit == null ? new ItemData(0, 0, QUALITIES.QUALITY_BAD) : new ItemData(BitConverter.ToInt32(bit, 0), 0, QUALITIES.QUALITY_GOOD); } public ItemData ReadUInt32(DeviceAddress address) { - byte[] bit = ReadBytes(address, 4); + byte[] bit = ReadBytes(address, 2); return bit == null ? new ItemData(0, 0, QUALITIES.QUALITY_BAD) : new ItemData(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) diff --git a/SCADA/Program/ModbusDriver/ModbusTCPDriver.cs b/SCADA/Program/ModbusDriver/ModbusTCPDriver.cs index 71d5d37..48e05f2 100644 --- a/SCADA/Program/ModbusDriver/ModbusTCPDriver.cs +++ b/SCADA/Program/ModbusDriver/ModbusTCPDriver.cs @@ -32,7 +32,14 @@ namespace ModbusDriver DeviceAddress dv = DeviceAddress.Empty; if (string.IsNullOrEmpty(address)) 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]) { case '0': @@ -145,16 +152,6 @@ namespace ModbusDriver set { _timeout = value; } } - byte _slaveId;//设备ID 单元号 字节号 - /// - /// 设备ID 单元号 字节号 - /// - public byte SlaveId - { - get { return _slaveId; } - set { _slaveId = value; } - } - List _grps = new List(20); public IEnumerable Groups { @@ -167,14 +164,13 @@ namespace ModbusDriver 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; _name = name; _server = server; _ip = ip; _timeout = timeOut; - if (!string.IsNullOrEmpty(spare1)) byte.TryParse(spare1, out _slaveId); } public bool Connect() diff --git a/SCADA/dll/ModbusDriver.dll b/SCADA/dll/ModbusDriver.dll index f316ef7dd961963d22a474b9a1db1469783a6b48..b10193d680b3ce240a8d931353961eb0ee4b4d45 100644 GIT binary patch literal 22016 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