所以我调用了我的函数,但是如何从设备中获取数据?也许有人可以提供帮助。
P.S。请不要建议使用现成的库,比如nmodbus - 和他们一起做了我所做的一切,我想自己尝试一下。谢谢。
static void Main(string[] args)
{
var serial = new SerialPort("COM6", 19200);
serial.Handshake = Handshake.None;
serial.Parity = Parity.None;
serial.DataBits = 8;
serial.StopBits = StopBits.One;
serial.Open();
serial.Write(ReadHoldingRegister(2, 1024, 16), 0, 8);
serial.Close();
Console.ReadLine();
}
#region Function 3
public static byte[] ReadHoldingRegister(int id, int startAddress, int length)
{
byte[] data = new byte[8];
byte High, Low;
data[0] = Convert.ToByte(id);
data[1] = Convert.ToByte(3);
byte[] _adr = BitConverter.GetBytes(startAddress - 1);
data[2] = _adr[1];
data[3] = _adr[0];
byte[] _length = BitConverter.GetBytes(length);
data[4] = _length[1];
data[5] = _length[0];
myCRC(data, 6, out High, out Low);
data[6] = Low;
data[7] = High;
return data;
}
#endregion
#region CRC
public static void myCRC(byte[] message, int length, out byte CRCHigh, out byte CRCLow)
{
ushort CRCFull = 0xFFFF;
for (int i = 0; i < length; i++)
{
CRCFull = (ushort)(CRCFull ^ message[i]);
for (int j = 0; j < 8; j++)
{
if ((CRCFull & 0x0001) == 0)
CRCFull = (ushort)(CRCFull >> 1);
else
{
CRCFull = (ushort)((CRCFull >> 1) ^ 0xA001);
}
}
}
CRCHigh = (byte)((CRCFull >> 8) & 0xFF);
CRCLow = (byte)(CRCFull & 0xFF);
}
#endregion
}
答案 0 :(得分:0)
处理响应不是“简单”的,您确实需要考虑错误,字符间和包间定时等问题。它也可能应该在单独的高优先级线程上。 Modbus规范具有一些处理状态图,这些状态图说明了(至少)应执行的操作。但是,作为一个非常简单,强力的民意调查示例,您可以从以下内容开始:
static Queue<byte> GetResponse(SerialPort serial, int timeoutMSecs)
{
Queue<byte> response = new Queue<byte>();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
while (stopwatch.ElapsedMilliseconds < timeoutMSecs)
{
if (serial.BytesToRead == 0) continue; // Nothing received, continue waiting
response.Enqueue((byte)serial.ReadByte()); // Add rx byte to queue
stopwatch.Reset(); // Reset timeout
if (response.Count > 255) break; // Maximum RTU packet?
}
return response;
}
在主要功能中
static void Main(string[] args)
{
...
serial.DiscardInBuffer(); // Clear any remaining rx bytes
serial.Write(ReadHoldingRegister(2, 1024, 16), 0, 8);
Queue<byte> response = GetResponse(serial, 5);
if (response.Count > 0)
{
// Process Response
// 1) check the CRC
// 2) if crc ok, check if it is an exception response
// 3) if not an exception check that it "matches" the request
// ...
}
...
}