From ab5c06df5e5134f7fc95f44bf779f827c94bde43 Mon Sep 17 00:00:00 2001 From: nikzori Date: Tue, 17 Dec 2024 16:36:42 +0300 Subject: [PATCH] added writing from single registers --- Main.cs | 65 +++++++++++++++++++--------------------------- Modbus.cs | 77 ++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 95 insertions(+), 47 deletions(-) diff --git a/Main.cs b/Main.cs index f79202c..b39ac93 100644 --- a/Main.cs +++ b/Main.cs @@ -182,7 +182,7 @@ namespace Gidrolock_Modbus_Scanner { try { - var send = await Modbus.ReadRegAsync(port, (byte)UpDown_ModbusID.Value, functionCode, address, length); + await Modbus.ReadRegAsync(port, (byte)UpDown_ModbusID.Value, functionCode, address, length); isAwaitingResponse = true; await Task.Delay(port.ReadTimeout).ContinueWith(_ => { @@ -431,7 +431,7 @@ namespace Gidrolock_Modbus_Scanner int portParsed = Int32.Parse(portText); await socket.ConnectAsync(ipText, portParsed); byte[] data = new byte[8]; - Modbus.BuildMessage(0x1E, 0x03, 128, 1, ref data); + Modbus.BuildReadMessage(0x1E, 0x03, 128, 1, ref data); AddLog("Sending to " + ipText + ":" + portText + ":" + Modbus.ByteArrayToString(data)); // set up an event listener to receive the response @@ -475,55 +475,44 @@ namespace Gidrolock_Modbus_Scanner { case (FunctionCode.WriteCoil): if (valueLower == "true" || valueLower == "1") - await Modbus.WriteSingle(port, (FunctionCode)functionCode, (byte)UpDown_ModbusID.Value, (ushort)address, 0xFF_00); + await Modbus.WriteSingleAsync(port, (FunctionCode)functionCode, (byte)UpDown_ModbusID.Value, (ushort)address, 0xFF_00); else if (valueLower == "false" || valueLower == "0") - await Modbus.WriteSingle(port, (FunctionCode)functionCode, (byte)UpDown_ModbusID.Value, (ushort)address, 0x00_00); + await Modbus.WriteSingleAsync(port, (FunctionCode)functionCode, (byte)UpDown_ModbusID.Value, (ushort)address, 0x00_00); else MessageBox.Show("Неподходящие значения для регистра типа Coil"); break; case (FunctionCode.WriteRegister): - short value; + short value = 0x00_00; + bool canWrite = false; if (IsHex(valueLower)) //assume this is hex { - try - { - value = Convert.ToInt16(valueLower, 16); - await Modbus.WriteSingle(port, (FunctionCode)functionCode, (byte)UpDown_ModbusID.Value, (ushort)address, - (ushort)value); - } + try { value = Convert.ToInt16(valueLower, 16); canWrite = true; } catch (Exception err) { MessageBox.Show(err.Message); } break; } else if (IsDec(valueLower)) { - try - { - value = Convert.ToInt16(valueLower); - await Modbus.WriteSingle(port, (FunctionCode)functionCode, (byte)UpDown_ModbusID.Value, (ushort)address, + try { value = Convert.ToInt16(valueLower); canWrite = true; } + catch (Exception err) { MessageBox.Show(err.Message); } + break; + } + else if (valueLower == "true" || valueLower == "1") + { + value = 0x00_01; + canWrite = true; + } + else if (valueLower == "false" || valueLower == "0") + { + canWrite = true; + } + if (canWrite) + { + byte[] _value = BitConverter.GetBytes(value); + Array.Reverse( _value ); + AddLog("Отправка сообщения: " + Modbus.ByteArrayToString(Modbus.BuildWriteSingleMessage((byte)UpDown_ModbusID.Value, (byte)functionCode, (ushort)address, _value))); + await Modbus.WriteSingleAsync(port, (FunctionCode)functionCode, (byte)UpDown_ModbusID.Value, (ushort)address, (ushort)value); - } - catch (Exception err) { MessageBox.Show(err.Message); } - break; - } - else if (valueLower == "true") - { - try - { - await Modbus.WriteSingle(port, (FunctionCode)functionCode, (byte)UpDown_ModbusID.Value, (ushort)address, - 0x01); - } - catch (Exception err) { MessageBox.Show(err.Message); } - break; - } - else if (valueLower == "false") - { - try - { - await Modbus.WriteSingle(port, (FunctionCode)functionCode, (byte)UpDown_ModbusID.Value, (ushort)address, - 0x00); - } - catch (Exception err) { MessageBox.Show(err.Message); } - break; } + else MessageBox.Show("Неподходящие значения для регистра типа Input Register"); break; default: break; diff --git a/Modbus.cs b/Modbus.cs index 697e22e..623e700 100644 --- a/Modbus.cs +++ b/Modbus.cs @@ -20,7 +20,7 @@ namespace Gidrolock_Modbus_Scanner } #region Build Message - public static byte[] BuildMessage(byte modbusID, byte functionCode, ushort address, ushort length, ref byte[] message) + public static byte[] BuildReadMessage(byte modbusID, byte functionCode, ushort address, ushort length, ref byte[] message) { //Array to receive CRC bytes: byte[] CRC = new byte[2]; @@ -39,6 +39,26 @@ namespace Gidrolock_Modbus_Scanner //Console.WriteLine("Message: " + msg); return message; } + public static byte[] BuildWriteSingleMessage(byte modbusID, byte functionCode, ushort address, byte[] data) + { + if (functionCode == 0x05 || functionCode == 0x06) + { + byte[] _message = new byte[8]; + byte[] CRC = new byte[2]; + + _message[0] = modbusID; + _message[1] = functionCode; + _message[2] = (byte)(address >> 8); + _message[3] = (byte)address; + _message[4] = data[0]; + _message[5] = data[1]; + GetCRC(_message, ref CRC); + _message[6] = CRC[0]; + _message[7] = CRC[1]; + return _message; + } + else return new byte[1] { 0xFF }; + } #endregion #region Read Functions @@ -53,9 +73,9 @@ namespace Gidrolock_Modbus_Scanner //Read functions are always 8 bytes long byte[] message = new byte[8]; - + //Build outgoing modbus message: - BuildMessage(slaveID, (byte)functionCode, address, length, ref message); + BuildReadMessage(slaveID, (byte)functionCode, address, length, ref message); //Send modbus message to Serial Port: try @@ -65,7 +85,7 @@ namespace Gidrolock_Modbus_Scanner } catch (Exception err) { - MessageBox.Show(err.Message); + MessageBox.Show(err.Message, "aeiou"); port.Close(); return false; } @@ -78,10 +98,45 @@ namespace Gidrolock_Modbus_Scanner } #endregion - + #region Write Single Coil/Register - public static async Task WriteSingle(SerialPort port, FunctionCode functionCode, byte slaveID, ushort address, uint value) + public static async Task WriteSingleAsync(SerialPort port, FunctionCode functionCode, byte slaveID, ushort address, ushort value) { + //Ensure port is open: + if (!port.IsOpen) + { + try + { + port.Open(); + } + catch (Exception err) + { + MessageBox.Show(err.Message); + return false; + } + } + //Clear in/out buffers: + port.DiscardOutBuffer(); + port.DiscardInBuffer(); + + //Build outgoing modbus message: + byte[] _value = BitConverter.GetBytes(value); + Array.Reverse(_value); + + byte[] message = BuildWriteSingleMessage(slaveID, (byte)functionCode, address, _value); + + //Send modbus message to Serial Port: + try + { + port.Write(message, 0, message.Length); + return true; + } + catch (Exception err) + { + MessageBox.Show(err.Message); + port.Close(); + return false; + } } #endregion @@ -104,12 +159,16 @@ namespace Gidrolock_Modbus_Scanner verbose = "Сообщение устройства не соответствует ожидаемой длине!"; return false; } - + } - public static string ByteArrayToString(byte[] bytes) + public static string ByteArrayToString(byte[] bytes, bool cleanEmpty = true) { - byte[] res = CleanByteArray(bytes); + byte[] res; + + if (cleanEmpty) + res = CleanByteArray(bytes); + else res = bytes; string dataString = BitConverter.ToString(res); string result = "";