From 5410bbe20b509e8d2b2ae04fadf5b469079b2eb6 Mon Sep 17 00:00:00 2001 From: lch <1627445470@qq.com> Date: Sun, 28 Apr 2024 14:58:58 +0800 Subject: [PATCH] =?UTF-8?q?mudbus=E8=AF=BB=E5=86=99plc=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ConsoleStarter/Program.cs | 24 ++- HybirdFrameworkCore/Utils/BitUtls.cs | 17 ++- .../ModbusTcpMaster/ModbusDecoder.cs | 115 ++++++++++++--- .../ModbusTcpMaster/ModbusProperty.cs | 15 +- .../ModbusTcpMaster/ModbusTcpMaster.cs | 139 ++++++++++++++---- .../ModbusTcpMaster/WaterCoolData.cs | 24 +-- 6 files changed, 255 insertions(+), 79 deletions(-) diff --git a/ConsoleStarter/Program.cs b/ConsoleStarter/Program.cs index b9ce4dc..0b92eeb 100644 --- a/ConsoleStarter/Program.cs +++ b/ConsoleStarter/Program.cs @@ -1,6 +1,8 @@ // See https://aka.ms/new-console-template for more information using System.Diagnostics; +using System.IO.Pipes; +using HslCommunication.Core; using HybirdFrameworkCore.Autofac.Attribute; using HybirdFrameworkCore.Utils; using HybirdFrameworkDriver.ModbusTcpMaster; @@ -12,6 +14,8 @@ internal class Program ModbusTcpMaster master = new ModbusTcpMaster() { Ip = "192.168.1.5", + //默认DataFormat.ABCD + //DataFormat = DataFormat.ABCD, ReadAction = ReadFunc }; @@ -30,19 +34,27 @@ internal class Program bool writeResult1 = master.WriteValue(coolData.Status); Debug.Assert(writeResult1, "写入失败"); //写入bit - coolData.DraughtFan2.Value = true; - bool writeResult3 = master.WriteValue(coolData.DraughtFan2); + coolData.DraughtFan1.Value = true; + bool writeResult3 = master.WriteValue(coolData.DraughtFan1); Debug.Assert(writeResult3, "写入失败"); + + coolData.Temperature1.Value = 12.7f; + bool writeResult5 = master.WriteValue(coolData.Temperature1); + Debug.Assert(writeResult5, "写入失败"); + #endregion 测试写 } - + private static WaterCoolData coolData = new WaterCoolData(); private static void ReadFunc(ModbusTcpMaster master) { - byte[]? bytes = master.BatchRead(0, 46); + byte[]? bytes = master.BatchRead(1, 46); if (bytes != null) { - WaterCoolData coolData = ModbusDecoder.Decode(bytes); - float temperature1Value = coolData.Temperature1.Value; + ModbusDecoder.Decode(bytes, coolData); + Debug.WriteLine("12.7f" + coolData.Temperature1.Value); + Debug.WriteLine("12" + coolData.Status.Value); + Debug.WriteLine("fasle" + coolData.CompressorState1.Value); + Debug.WriteLine("18" + coolData.ushortType.Value); } } diff --git a/HybirdFrameworkCore/Utils/BitUtls.cs b/HybirdFrameworkCore/Utils/BitUtls.cs index b95d795..8f652f0 100644 --- a/HybirdFrameworkCore/Utils/BitUtls.cs +++ b/HybirdFrameworkCore/Utils/BitUtls.cs @@ -196,9 +196,20 @@ public static class BitUtls #endregion #region Decode Value - - public static object Bytes2Value(byte[] bytes, Type propertyType, int start, int length, double scale, int round, - double offset) + /// + /// + /// + /// 原始字节数组 + /// 字段类型:bool byte等 + /// 当前字段第一个bit所处开始位置 + /// bit的数量 + /// 精度 + /// 保留几位小数 + /// 位偏移 + /// + /// + public static object Bytes2Value(byte[] bytes, Type propertyType, int start, int length, + double scale, int round,double offset) { if (propertyType == BOOLEAN) { diff --git a/HybirdFrameworkDriver/ModbusTcpMaster/ModbusDecoder.cs b/HybirdFrameworkDriver/ModbusTcpMaster/ModbusDecoder.cs index 1280a60..8528ab0 100644 --- a/HybirdFrameworkDriver/ModbusTcpMaster/ModbusDecoder.cs +++ b/HybirdFrameworkDriver/ModbusTcpMaster/ModbusDecoder.cs @@ -1,4 +1,6 @@ -using HybirdFrameworkCore.Utils; +using HslCommunication.Core; +using HslCommunication.Secs.Types; +using HybirdFrameworkCore.Utils; using log4net; namespace HybirdFrameworkDriver.ModbusTcpMaster; @@ -7,13 +9,12 @@ public static class ModbusDecoder { private static readonly ILog Log = LogManager.GetLogger(typeof(ModbusDecoder)); - public static T Decode(byte[] bytes) where T : class, new() + public static T Decode(byte[] bytes, T t) where T : class, new() { - T t = new T(); List fields = t.GetType().GetProperties() .Where(it => it.PropertyType.GetGenericTypeDefinition() == typeof(ModbusProperty<>)) .Select(p => p.GetValue(t)).ToList(); - + //startRegisterNo 获得整个对象的起始寄存器数值 int startRegisterNo = Int32.MaxValue; foreach (object? field in fields) { @@ -26,29 +27,95 @@ public static class ModbusDecoder } } } - + byte[] decodeUseBytes = new byte[bytes.Length]; + switch (ModbusTcpMaster.DataFormat) + { + case DataFormat.ABCD: + for (int i = 0; i < bytes.Length; i++) + { + if (i % 2 == 0) + decodeUseBytes[i + 1] = bytes[i]; + else + decodeUseBytes[i - 1] = bytes[i]; + } + break; + case DataFormat.BADC: + decodeUseBytes = bytes; + break; + } foreach (object? field in fields) { switch (field) { - case ModbusProperty property: - { - SetPropertyValue(startRegisterNo, property, bytes); - break; - } + case ModbusProperty boolProperty: + { + SetPropertyValue(startRegisterNo, boolProperty, decodeUseBytes); + //SetPropertyValue(boolProperty.RegisterNo, boolProperty, decodeUseBytes); + break; + } + case ModbusProperty byteProperty: + { + SetPropertyValue(startRegisterNo, byteProperty, decodeUseBytes); + //SetPropertyValue(byteProperty.RegisterNo, byteProperty, decodeUseBytes); + break; + } + case ModbusProperty sbyteProperty: + { + //SetPropertyValue(sbyteProperty.RegisterNo, sbyteProperty, decodeUseBytes); + SetPropertyValue(startRegisterNo, sbyteProperty, decodeUseBytes); + break; + } + case ModbusProperty shortProperty: + { + SetPropertyValue(startRegisterNo, shortProperty, decodeUseBytes); + //SetPropertyValue(shortProperty.RegisterNo, shortProperty, decodeUseBytes); + break; + } + case ModbusProperty ushortProperty: + { + SetPropertyValue(startRegisterNo, ushortProperty, decodeUseBytes); + // SetPropertyValue(ushortProperty.RegisterNo, ushortProperty, decodeUseBytes); + break; + } + case ModbusProperty intProperty: + { + SetPropertyValue(startRegisterNo, intProperty, decodeUseBytes); + // SetPropertyValue(intProperty.RegisterNo, intProperty, decodeUseBytes); + break; + } + case ModbusProperty uintProperty: + { + SetPropertyValue(startRegisterNo, uintProperty, decodeUseBytes); + // SetPropertyValue(uintProperty.RegisterNo, uintProperty, decodeUseBytes); + break; + } case ModbusProperty floatProperty: - { - SetPropertyValue(startRegisterNo, floatProperty, bytes); - break; - } + { + SetPropertyValue(startRegisterNo, floatProperty, decodeUseBytes); + // SetPropertyValue(floatProperty.RegisterNo, floatProperty, decodeUseBytes); + break; + } + case ModbusProperty doubleProperty: + { + SetPropertyValue(startRegisterNo, doubleProperty, decodeUseBytes); + // SetPropertyValue(doubleProperty.RegisterNo, doubleProperty, decodeUseBytes); + break; + } + case ModbusProperty stringProperty: + { + SetPropertyValue(startRegisterNo, stringProperty, decodeUseBytes); + // SetPropertyValue(stringProperty.RegisterNo, stringProperty, decodeUseBytes); + break; + } + } } - return t; } private static void SetPropertyValue(int startRegisterNo, ModbusProperty field, byte[] bytes) { + int registerNo = field.RegisterNo; int start = field.Start; int length = field.Length; @@ -59,15 +126,17 @@ public static class ModbusDecoder start = (registerNo - startRegisterNo) * 16 + start; - length = type switch - { - ModbusDataType.Byte => length * 8, - ModbusDataType.Register => length * 16, - _ => length - }; - Type valueType = typeof(T); - + if (typeof(T) == typeof(byte)) + length = length * 8; + else + { + length = type switch + { + ModbusDataType.Register => length * 16, + _ => length + }; + } object value = BitUtls.Bytes2Value(bytes, valueType, start, length, scale, round, offset); field.Value = (T)value; } diff --git a/HybirdFrameworkDriver/ModbusTcpMaster/ModbusProperty.cs b/HybirdFrameworkDriver/ModbusTcpMaster/ModbusProperty.cs index b4d8b5c..257a794 100644 --- a/HybirdFrameworkDriver/ModbusTcpMaster/ModbusProperty.cs +++ b/HybirdFrameworkDriver/ModbusTcpMaster/ModbusProperty.cs @@ -26,10 +26,18 @@ public class ModbusProperty : IModbusProperty public int Round { get; set; } public double Offset { get; set; } public T Value { get; set; } - + /// + /// + /// + /// 寄存器编号 + /// 根据类型:Register为第几个寄存器 + /// 根据类型:Register 为 几个寄存器 + /// Register/Bit + /// 精度 + /// 保留几位小数 + /// 偏移量 public ModbusProperty(int registerNo, int start = 0, int length = 1, ModbusDataType type = ModbusDataType.Register, - double scale = 1, - int round = 0, double offset = 0) + double scale = 1,int round = 0, double offset = 0) { this.RegisterNo = registerNo; this.Start = start; @@ -50,6 +58,5 @@ public class ModbusProperty : IModbusProperty public enum ModbusDataType { Bit, - Byte, Register } \ No newline at end of file diff --git a/HybirdFrameworkDriver/ModbusTcpMaster/ModbusTcpMaster.cs b/HybirdFrameworkDriver/ModbusTcpMaster/ModbusTcpMaster.cs index 0316fd0..ef60ba5 100644 --- a/HybirdFrameworkDriver/ModbusTcpMaster/ModbusTcpMaster.cs +++ b/HybirdFrameworkDriver/ModbusTcpMaster/ModbusTcpMaster.cs @@ -1,4 +1,5 @@ -using System.Collections; +using System; +using System.Collections; using HslCommunication; using HslCommunication.Core; using HslCommunication.ModBus; @@ -15,7 +16,7 @@ public class ModbusTcpMaster public string Ip { get; set; } = "192.168.1.5"; public int Port { get; set; } = 502; - public DataFormat DataFormat { get; set; } = DataFormat.ABCD; + public static DataFormat DataFormat { get; set; } = DataFormat.ABCD; public int Duration { get; set; } = 1000; public bool Connected { get; set; } = false; @@ -91,7 +92,7 @@ public class ModbusTcpMaster { try { - ReadAction(this); + ReadAction(this); Thread.Sleep(Duration); } catch (Exception e) @@ -137,7 +138,6 @@ public class ModbusTcpMaster GetLog().Warn($"write property{property.RegisterNo} null value"); return false; } - bool result = false; ModbusDataType dataType = property.Type; int start = property.Start; @@ -145,45 +145,122 @@ public class ModbusTcpMaster int registerNo = property.RegisterNo - 40000; byte[] setValue = BitUtls.Value2Bytes(value, property.Scale, property.Offset); OperateResult operateResult; - + switch (dataType) { - case ModbusDataType.Byte: - - start = start % 2 == 0 ? start / 2 : start / 2 + 1; - operateResult = ModbusTcpNet.Write("x=6;" + (registerNo + start), setValue); - result = operateResult.IsSuccess; - break; case ModbusDataType.Register: - operateResult = ModbusTcpNet.Write("x=16;" + (registerNo + start), setValue); - result = operateResult.IsSuccess; - break; - case ModbusDataType.Bit: - start = start % 16 == 0 ? start / 16 : start / 16 + 1; - length = length % 8 == 0 ? length / 8 : length / 8 + 1; - OperateResult readResult = - ModbusTcpNet.Read("x=3;" + (registerNo + start), (ushort)length); - - if (readResult.IsSuccess) + if (setValue.Length < length * 2) { - byte[] bytes = readResult.Content; - BitArray bitArray = new BitArray(bytes); - int index = 0; - for (int i = property.Start % 16; i < property.Length; i++) + //byte 需要读取寄存器中的内容 + if (typeof(T) == typeof(byte)) { - bitArray[i] = (setValue[index / 8] & (1 << (index % 8))) > 0; - index++; + OperateResult readResultRegister = ModbusTcpNet.Read("x=3;" + (registerNo), 1); + if (readResultRegister.IsSuccess) + { + switch (DataFormat) + { + case DataFormat.ABCD: + readResultRegister.Content[1] = setValue[0]; + break; + case DataFormat.BADC: + readResultRegister.Content[0] = setValue[0]; + break; + } + operateResult = ModbusTcpNet.Write("x=16;" + (registerNo), readResultRegister.Content); + result = operateResult.IsSuccess; + } } + //其他类型 String 占用几个寄存器 直接补0 + else + { + byte[] preWriteCont = new byte[length * 2]; - bitArray.CopyTo(bytes, 0); + switch (DataFormat) + { + case DataFormat.ABCD: + for (int i = 0; i < setValue.Length; i++) + { + if (i % 2 == 0) + preWriteCont[i + 1] = setValue[i]; + else + preWriteCont[i - 1] = setValue[i]; + } + break; + case DataFormat.BADC: + Array.Copy(setValue, preWriteCont, setValue.Length); + break; + } + operateResult = ModbusTcpNet.Write("x=16;" + (registerNo), preWriteCont); + result = operateResult.IsSuccess; + } - operateResult = ModbusTcpNet.Write("x=6;" + (registerNo + start), bytes); - result = operateResult.IsSuccess; } + else if (setValue.Length == length * 2) + { + byte[] preWriteCont = new byte[setValue.Length]; + switch (DataFormat) + { + case DataFormat.ABCD: + for (int i = 0; i < setValue.Length; i++) + { + if (i % 2 == 0) + preWriteCont[i + 1] = setValue[i]; + else + preWriteCont[i - 1] = setValue[i]; + } + break; + case DataFormat.BADC: + //Array.Copy(setValue, preWriteCont, setValue.Length); + break; + } + operateResult = ModbusTcpNet.Write("x=16;" + (registerNo), preWriteCont); + result = operateResult.IsSuccess; + } + break; + case ModbusDataType.Bit: + result = WriteRegisterOneBit(registerNo, start, Convert.ToBoolean(value)); break; } - return result; } + /// + /// 写寄存器中的一个bit + /// + /// + /// + /// + /// + public bool WriteRegisterOneBit(int addr, int location, bool boolResult) + { + if (!Connected) return false; + bool result = false; + ushort registerValue1 = 0x1234; + ushort mask = 0x1234; + OperateResult readResult = ModbusTcpNet.Read("x=3;" + addr.ToString(), 1); + if (readResult.IsSuccess) + { + if (location >= 0 && location <= 15) + { + registerValue1 = ModbusTcpNet.ByteTransform.TransUInt16(readResult.Content, 0); + if (boolResult) + { + mask = (ushort)(1 << location); + registerValue1 |= mask; + } + else + { + mask = (ushort)(~(1 << location)); + registerValue1 &= mask; + } + OperateResult writeResult = ModbusTcpNet.Write("x=6;" + addr, registerValue1); + if (writeResult.IsSuccess) + { + result = true; + } + } + } + return result; + } + } \ No newline at end of file diff --git a/HybirdFrameworkDriver/ModbusTcpMaster/WaterCoolData.cs b/HybirdFrameworkDriver/ModbusTcpMaster/WaterCoolData.cs index f60b97f..5b6b30b 100644 --- a/HybirdFrameworkDriver/ModbusTcpMaster/WaterCoolData.cs +++ b/HybirdFrameworkDriver/ModbusTcpMaster/WaterCoolData.cs @@ -17,20 +17,20 @@ public class WaterCoolData public ModbusProperty CompressorState4 { get; set; } = new(40003, 10, type: ModbusDataType.Bit); public ModbusProperty ChargePump { get; set; } = new(40003, 11, type: ModbusDataType.Bit); - public ModbusProperty Temperature1 { get; set; } = new(40004, scale: 0.1, round: 1); - public ModbusProperty Temperature2 { get; set; } = new(40005, scale: 0.1, round: 1); - public ModbusProperty Temperature3 { get; set; } = new(40006, scale: 0.1, round: 1); - public ModbusProperty Temperature4 { get; set; } = new(40007, scale: 0.1, round: 1); - public ModbusProperty Temperature5 { get; set; } = new(40008, scale: 0.1, round: 1); - public ModbusProperty Temperature6 { get; set; } = new(40009, scale: 0.1, round: 1); - public ModbusProperty WaterDischarge { get; set; } = new(40010, scale: 0.1, round: 1); - public ModbusProperty CompressorTemperature1 { get; set; } = new(40011, scale: 0.1, round: 1); - public ModbusProperty CompressorTemperature2 { get; set; } = new(40012, scale: 0.1, round: 1); - public ModbusProperty CompressorTemperature3 { get; set; } = new(40013, scale: 0.1, round: 1); - public ModbusProperty CompressorTemperature4 { get; set; } = new(40014, scale: 0.1, round: 1); + public ModbusProperty Temperature1 { get; set; } = new(40004, length: 2, scale: 0.1, round: 1); + public ModbusProperty Temperature2 { get; set; } = new(40005, length: 2, scale: 0.1, round: 1); + public ModbusProperty Temperature3 { get; set; } = new(40006, length: 2, scale: 0.1, round: 1); + public ModbusProperty Temperature4 { get; set; } = new(40007, length: 2, scale: 0.1, round: 1); + public ModbusProperty Temperature5 { get; set; } = new(40008, length: 2, scale: 0.1, round: 1); + public ModbusProperty Temperature6 { get; set; } = new(40009, length: 2, scale: 0.1, round: 1); + public ModbusProperty WaterDischarge { get; set; } = new(40010, length: 2, scale: 0.1, round: 1); + public ModbusProperty CompressorTemperature1 { get; set; } = new(40011, length: 2, scale: 0.1, round: 1); + public ModbusProperty CompressorTemperature2 { get; set; } = new(40012, length: 2, scale: 0.1, round: 1); + public ModbusProperty CompressorTemperature3 { get; set; } = new(40013, length: 2, scale: 0.1, round: 1); + public ModbusProperty CompressorTemperature4 { get; set; } = new(40014, length: 2, scale: 0.1, round: 1); public ModbusProperty ushortType { get; set; } = new(40015); - + public ModbusProperty ElectromagneticStatus1 { get; set; } = new(40023, scale: 0.1, round: 1); public ModbusProperty ElectromagneticStatus2 { get; set; } = new(40024, scale: 0.1, round: 1); } \ No newline at end of file