[Modbus] 如何 用 C# 開發 Modbus Master Protocol - (11) 實作 HexModbusDataConvert
續上篇,產出的資料若都是 byte[] 實在很難閱讀,所以這個 HexModbusDataConvert 類別專處理資料格式轉換
這只是很簡單的進制轉換,要參考的資料很多
[C#.NET] 開發通訊協定必須要會的技巧
[C#.NET] 處理通訊協定的事前準備
[C#.NET] 浮點數 轉 Hexadecimal
[C#.NET] Hexadecimal 字串格式轉時間格式
[C#][VB.NET] 進制轉換 (2進制、8進制、16進制)轉10進制
[VB6][C#][VB.Net] 進制轉換,2進制轉(10進制、8進制、16進制)
{ public override byte[] ResultArray { get; internal set; } public override IEnumerable<long> ToDecimal(byte[] ResultArray, EnumModbusIntegralUnit Unit) { var length = (int)Unit; if (ResultArray == null) { throw new ArgumentNullException("ResultArray"); } if (ResultArray.Length <= 0 || ResultArray.Length < length) { throw new FormatException("ResultArray"); } this.ResultArray = ResultArray; List<long> resultList = new List<long>(); for (int i = 0; i < ResultArray.Length; i = i + length) { using (MemoryStream memory = new MemoryStream()) { memory.Write(ResultArray, i, length); var tempArray = memory.ToArray(); long result = 0; if (BitConverter.IsLittleEndian) { Array.Reverse(tempArray); } switch (Unit) { case EnumModbusIntegralUnit.Byte: result = tempArray[0]; break; case EnumModbusIntegralUnit.Word: result = BitConverter.ToInt16(tempArray, 0); break; case EnumModbusIntegralUnit.DWord: result = BitConverter.ToInt32(tempArray, 0); break; case EnumModbusIntegralUnit.QWord: result = BitConverter.ToInt64(tempArray, 0); break; default: throw new ArgumentOutOfRangeException("Unit"); } resultList.Add(result); } } return resultList; } public override IEnumerable<long> ToOctal(byte[] ResultArray, EnumModbusIntegralUnit Unit) { var length = (int)Unit; if (ResultArray == null) { throw new ArgumentNullException("ResultArray"); } if (ResultArray.Length <= 0 || ResultArray.Length < length) { throw new FormatException("ResultArray"); } this.ResultArray = ResultArray; List<long> resultList = new List<long>(); for (int i = 0; i < ResultArray.Length; i = i + length) { using (MemoryStream memory = new MemoryStream()) { memory.Write(ResultArray, i, length); var tempArray = memory.ToArray(); if (BitConverter.IsLittleEndian) { Array.Reverse(tempArray); } switch (Unit) { case EnumModbusIntegralUnit.Byte: var dec = tempArray[0]; var oct = int.Parse(Convert.ToString(dec, 8)); resultList.Add(oct); break; case EnumModbusIntegralUnit.Word: var decShort = BitConverter.ToInt16(tempArray, 0); var octShort = int.Parse(Convert.ToString(decShort, 8)); resultList.Add(octShort); break; case EnumModbusIntegralUnit.DWord: var decInt = BitConverter.ToInt32(tempArray, 0); var octInt = long.Parse(Convert.ToString(decInt, 8)); resultList.Add(octInt); break; case EnumModbusIntegralUnit.QWord: var decLong = BitConverter.ToInt32(tempArray, 0); var octLong = long.Parse(Convert.ToString(decLong, 8)); resultList.Add(octLong); break; default: throw new ArgumentOutOfRangeException("Unit"); } } } return resultList; } public override IEnumerable<string> ToHexadecimal(byte[] ResultArray, EnumModbusIntegralUnit Unit) { var length = (int)Unit; if (ResultArray == null) { throw new ArgumentNullException("ResultArray"); } if (ResultArray.Length <= 0 || ResultArray.Length < length) { throw new FormatException("ResultArray"); } this.ResultArray = ResultArray; List<string> resultList = new List<string>(); for (int i = 0; i < ResultArray.Length; i = i + length) { using (MemoryStream memory = new MemoryStream()) { memory.Write(ResultArray, i, length); var tempArray = memory.ToArray(); var result = BitConverter.ToString(tempArray).Replace("-", ""); resultList.Add(result); } } return resultList; } public override IEnumerable<string> ToBinary(byte[] ResultArray, EnumModbusIntegralUnit Unit) { var length = (int)Unit; if (ResultArray == null) { throw new ArgumentNullException("ResultArray"); } if (ResultArray.Length <= 0 || ResultArray.Length < length) { throw new FormatException("ResultArray"); } this.ResultArray = ResultArray; List<string> resultList = new List<string>(); for (int i = 0; i < ResultArray.Length; i = i + length) { using (MemoryStream memory = new MemoryStream()) { memory.Write(ResultArray, i, length); var tempArray = memory.ToArray(); if (BitConverter.IsLittleEndian) { Array.Reverse(tempArray); } var bin = ""; switch (Unit) { case EnumModbusIntegralUnit.Byte: bin = Convert.ToString(tempArray[0], 2).PadLeft(8, '0'); break; case EnumModbusIntegralUnit.Word: var decShort = BitConverter.ToInt16(tempArray, 0); bin = Convert.ToString(decShort, 2).PadLeft(16, '0'); break; case EnumModbusIntegralUnit.DWord: var decInt = BitConverter.ToInt32(tempArray, 0); bin = Convert.ToString(decInt, 2).PadLeft(32, '0'); break; case EnumModbusIntegralUnit.QWord: var decLong = BitConverter.ToInt64(tempArray, 0); bin = Convert.ToString(decLong, 2).PadLeft(64, '0'); break; default: throw new ArgumentOutOfRangeException("Unit"); } resultList.Add(bin); } } return resultList; } public override IEnumerable<float> ToFloat(byte[] ResultArray) { var length = 4; if (ResultArray == null) { throw new ArgumentNullException("ResultArray"); } if (ResultArray.Length <= 0 || ResultArray.Length < length) { throw new FormatException("ResultArray"); } this.ResultArray = ResultArray; int count = ResultArray.Length / length; List<float> resultList = new List<float>(); for (int i = 0; i < count * length; i = i + length) { using (MemoryStream memory = new MemoryStream()) { memory.Write(ResultArray, i + 1, 1); memory.Write(ResultArray, i, 1); memory.Write(ResultArray, i + 3, 1); memory.Write(ResultArray, i + 2, 1); var resultArray = memory.ToArray(); float result = BitConverter.ToSingle(resultArray, 0); resultList.Add(result); } } return resultList; } public override IEnumerable<double> ToDouble(byte[] ResultArray) { var length = 8; if (ResultArray == null) { throw new ArgumentNullException("ResultArray"); } if (ResultArray.Length <= 0 || ResultArray.Length < length) { throw new FormatException("ResultArray"); } this.ResultArray = ResultArray; int count = ResultArray.Length / length; List<double> resultList = new List<double>(); for (int i = 0; i < count * length; i = i + length) { using (MemoryStream memory = new MemoryStream()) { memory.Write(ResultArray, i + 1, 1); memory.Write(ResultArray, i, 1); memory.Write(ResultArray, i + 3, 1); memory.Write(ResultArray, i + 2, 1); memory.Write(ResultArray, i + 5, 1); memory.Write(ResultArray, i + 4, 1); memory.Write(ResultArray, i + 7, 1); memory.Write(ResultArray, i + 6, 1); var resultArray = memory.ToArray(); double result = BitConverter.ToDouble(resultArray, 0); resultList.Add(result); } } return resultList; } }
此類別,會用到的列舉
{
Byte = 1, Word = 2, DWord = 4, QWord = 8
}
前面幾篇文章都會看的到的 ModbusUtility 類別,收納了一些雜像功能,不知如何分類的都被丟到這裡來,比如計算CRC / LRC
{ public readonly static string ASCII_START_SYMBOL = ":"; public readonly static string ASCII_END_SYMBOL = "\r\n"; private CRCManager m_CrcManager = new CRCManager(); private AbsCRCProvider m_CrcProvider; private string[] s_Symbol = new string[] { " ", ",", "-" }; public string BytesToBinaryString(byte[] HexArray) { StringBuilder sb = new StringBuilder(); foreach (var b in HexArray) { sb.Append(Convert.ToString(b, 2).PadLeft(8, '0')); } return sb.ToString(); } public byte[] HexStringToBytes(string Hex) { string filter = s_Symbol.Aggregate(Hex, (current, symbol) => current.Replace(symbol, "")); return Enumerable.Range(0, filter.Length) .Where(x => x % 2 == 0) .Select(x => Convert.ToByte(filter.Substring(x, 2), 16)) .ToArray(); } public string BytesToHexString(byte[] HexArray) { StringBuilder sb = new StringBuilder(); foreach (var b in HexArray) { sb.Append(b.ToString("X2")); } return sb.ToString(); } public string CalculateLRC(byte[] DataArray) { if (DataArray == null) throw new ArgumentNullException("data"); byte lrc = 0; foreach (byte b in DataArray) { lrc += b; } lrc = (byte)((lrc ^ 0xFF) + 1); var hex = lrc.ToString("X2"); return hex; } public byte[] CalculateCRC(byte[] DataArray) { if (m_CrcProvider == null) { m_CrcProvider = m_CrcManager.CreateCRCProvider(EnumCRCProvider.CRC16Modbus); } var crcArray = m_CrcProvider.GetCRC(DataArray).CrcArray; Array.Reverse(crcArray); return crcArray; } }
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET