Files
gidrolock-configurator/Modbus.cs

139 lines
4.3 KiB
C#
Raw Normal View History

2024-11-05 10:31:38 +03:00
using System;
using System.IO.Ports;
using System.Runtime;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace Gidrolock_Modbus_Scanner
{
public static class Modbus
{
#region CRC Computation
static void GetCRC(byte[] message, ref byte[] CRC)
{
//Function expects a modbus message of any length as well as a 2 byte CRC array in which to
//return the CRC values:
ushort CRCFull = 0xFFFF;
byte CRCHigh = 0xFF, CRCLow = 0xFF;
char CRCLSB;
for (int i = 0; i < (message.Length) - 2; i++)
{
CRCFull = (ushort)(CRCFull ^ message[i]);
for (int j = 0; j < 8; j++)
{
CRCLSB = (char)(CRCFull & 0x0001);
CRCFull = (ushort)((CRCFull >> 1) & 0x7FFF);
if (CRCLSB == 1)
CRCFull = (ushort)(CRCFull ^ 0xA001);
}
}
CRC[1] = CRCHigh = (byte)((CRCFull >> 8) & 0xFF);
CRC[0] = CRCLow = (byte)(CRCFull & 0xFF);
}
#endregion
#region Build Message
2024-11-05 16:57:05 +03:00
public static void BuildMessage(byte address, byte type, ushort start, ushort length, ref byte[] message)
2024-11-05 10:31:38 +03:00
{
//Array to receive CRC bytes:
byte[] CRC = new byte[2];
message[0] = address;
message[1] = type;
message[2] = (byte)(start >> 8);
message[3] = (byte)start;
2024-11-05 16:57:05 +03:00
message[4] = (byte)(length >> 8);
message[5] = (byte)length;
2024-11-05 10:31:38 +03:00
GetCRC(message, ref CRC);
message[message.Length - 2] = CRC[0];
message[message.Length - 1] = CRC[1];
string msg = BitConverter.ToString(message);
Console.WriteLine("Message: " + msg);
}
#endregion
#region Function 3 - Read Holding Registers
2024-11-05 16:57:05 +03:00
public static async Task<bool> ReadRegAsync(SerialPort port, FunctionCode functionCode, byte address, ushort start, ushort length)
2024-11-05 10:31:38 +03:00
{
//Ensure port is open:
if (port.IsOpen)
{
//Clear in/out buffers:
port.DiscardOutBuffer();
port.DiscardInBuffer();
2024-11-05 16:57:05 +03:00
//Read functions are always 8 bytes long
2024-11-05 10:31:38 +03:00
byte[] message = new byte[8];
2024-11-05 16:57:05 +03:00
2024-11-05 10:31:38 +03:00
//Build outgoing modbus message:
2024-11-05 16:57:05 +03:00
BuildMessage(address, (byte)(1 + (int)functionCode), start, length, ref message);
2024-11-05 10:31:38 +03:00
//Send modbus message to Serial Port:
try
{
await Task.Run(() => { port.Write(message, 0, message.Length); });
return true;
}
catch (Exception err)
{
MessageBox.Show(err.Message);
port.Close();
return false;
}
}
else
{
MessageBox.Show("Порт не открыт");
return false;
}
}
#endregion
2024-11-05 16:57:05 +03:00
/// <summary>
/// Parses a byte array into a string.
/// </summary>
/// <param name="command"></param>
/// <returns>string</returns>
public static string ParseByteArray(byte[] bytes)
{
int length = bytes.Length - 1;
// snip off the empty bytes at the end
for (int i = length; i >= 0; i--)
{
if (bytes[i] != 0)
{
length = i + 1;
break;
}
}
byte[] res = new byte[length];
for (int i = 0; i < length; i++)
res[i] = bytes[i];
string dataString = BitConverter.ToString(res);
string result = "";
for (int i = 0; i < dataString.Length; i++)
{
if (dataString[i] == '-')
result += " ";
else result += dataString[i];
}
return result;
}
2024-11-05 10:31:38 +03:00
}
}