我刚刚开始使用此 Modbus TCP 库 ( https://github.com/stephanstricker/modbusTCP/tree/master/ModbusTCP/ModbusTCP ) 和本文档来引用 Function 20 ( http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf ) 的项目。问题是它不支持功能代码 20(阅读一般引用/文件)。现在我只是想创建自己的函数来处理它,但是我得到的响应是一个 10 和 1 的两个字节数组。
这是我尝试使用的请求 header :
private byte[] CreateReadFileHeader(ushort id, byte unit, byte count, ushort fileNumber, ushort recordNumber, ushort recordLength)
{
byte[] data = new byte[13];
byte[] _id = BitConverter.GetBytes((short)id);
data[0] = _id[1]; // Transaction ID high byte
data[1] = _id[0]; // Transaction ID low byte
data[2] = 11; // Packet Length
data[3] = unit; // Slave address
data[4] = fctReadFile; // Function code = 20
//byte[] _adr = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)startAddress));
data[5] = 7; // Byte Count 0x07 to 0xF5 bytes
data[6] = 6; // Reference Type
byte[] _FileNum = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)fileNumber));
data[7] = 0; // File Number Hi
data[8] = 1; // File Number Lo
byte[] _RecordNum = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder(10000));
data[9] = _RecordNum[0]; // Record Number Hi
data[10] = _RecordNum[1]; // Record Number Lo
byte[] _RecordLength = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)recordLength));
data[11] = 0; // Record Length Hi
data[12] = 6; // Record Length Lo
return data;
}
这是调用请求的代码:
private byte[] WriteSyncData(byte[] write_data, ushort id)
{
if (tcpSynCl.Connected)
{
try
{
tcpSynCl.Send(write_data, 0, write_data.Length, SocketFlags.None);
int result = tcpSynCl.Receive(tcpSynClBuffer, 0, tcpSynClBuffer.Length, SocketFlags.None);
byte unit = tcpSynClBuffer[6];
byte function = tcpSynClBuffer[7];
byte[] data;
if (result == 0) CallException(id, unit, write_data[7], excExceptionConnectionLost);
// ------------------------------------------------------------
// Response data is slave exception
if (function > excExceptionOffset)
{
function -= excExceptionOffset;
CallException(id, unit, function, tcpSynClBuffer[8]);
return null;
}
// ------------------------------------------------------------
// Write response data
else if ((function >= fctWriteSingleCoil) && (function != fctReadWriteMultipleRegister)&&(function!=fctReadFile))
{
data = new byte[2];
Array.Copy(tcpSynClBuffer, 10, data, 0, 2);
}
// ------------------------------------------------------------
// Read response data
else
{
data = new byte[tcpSynClBuffer[8]];
Array.Copy(tcpSynClBuffer, 9, data, 0, tcpSynClBuffer[8]);
}
return data;
}
catch (SystemException)
{
CallException(id, write_data[6], write_data[7], excExceptionConnectionLost);
}
}
else CallException(id, write_data[6], write_data[7], excExceptionConnectionLost);
return null;
}
TCP 同步缓冲区返回 [0,0,11,1,0,3,6,128,1,0,10,1,0,0,0,...]
更新:
我将请求 header 修改为此。
private byte[] CreateReadFileHeader(ushort id, byte unit, byte count, ushort fileNumber, ushort recordNumber, ushort recordLength)
{
byte[] data = new byte[17];
byte[] _id = BitConverter.GetBytes((short)id);
data[0] = 0;//_id[1]; // Transaction ID high byte
data[1] = 0;//_id[0]; // Transaction ID low byte
byte[] _size = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)(11)));
data[2] = 0; //Protocol identifier
data[3] = 0; //Protocol identifier
data[4] = 0; // Packet Length
data[5] = 11; // Packet Length
data[6] = unit; //Unit Identifier
data[7] = fctReadFile; // Function code
//byte[] _adr = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)startAddress));
data[8] = 0; // Byte Count 0x07 to 0xF5 bytes
data[9] = 7; // Byte Count 0x07 to 0xF5 bytes
data[10] = 6; // Reference Type
byte[] _FileNum = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)fileNumber));
data[11] = 0; // File Number Hi
data[12] = 1; // File Number Lo
byte[] _RecordNum = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder(10000));
data[13] = _RecordNum[0]; // Record Number Hi
data[14] = _RecordNum[1]; // Record Number Lo
byte[] _RecordLength = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)recordLength));
data[15] =0; // Record Length Hi
data[16] =1; // Record Length Lo
return data;
}
//I use this function to call the request
public void ReadFile(ushort id, byte unit, ref byte[] values)
{
byte[] write_data = CreateReadFileHeader(id, unit, 7, 1, 10000, 6);
tcpSynCl.Send(write_data, 0, write_data.Length, SocketFlags.None);
int result = tcpSynCl.Receive(tcpSynClBuffer, 0, tcpSynClBuffer.Length, SocketFlags.None);
values = tcpSynClBuffer;
}
现在返回:
[0,0,0,0,0,5,1,20,4,0,0,0,..]
最佳答案
我明白了。我所做的更新创建了正确的 header ,但是文件可能已损坏,因此我决定读取另一个文件并且成功了。
这是我的代码:
public void ReadFile(ushort id, byte unit, ref byte[] values)
{
byte[] write_data = CreateReadFileHeader(id, unit, 7, 2, 0, 56797);
byte[] Buffer = new byte[2048];
tcpSynCl.Send(write_data, 0, write_data.Length, SocketFlags.None);
int result = tcpSynCl.Receive(Buffer, 0, Buffer.Length, SocketFlags.None);
values = Buffer;
}
private byte[] CreateReadFileHeader(ushort id, byte unit, byte count, ushort fileNumber, ushort recordNumber, ushort recordLength)
{
byte[] data = new byte[17];
byte[] _id = BitConverter.GetBytes((short)id);
data[0] = _id[1]; // Transaction ID high byte
data[1] = _id[0]; // Transaction ID low byte
byte[] _size = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)(11)));
data[2] = 0;
data[3] = 0;
data[4] = 0; // Packet Length
data[5] = 11; // Packet Length
data[6] = unit; // Slave address
data[7] = fctReadFile; // Function code
//byte[] _adr = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)startAddress));
byte[] _Count = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)count));
data[8] = _Count[0]; // Byte Count 0x07 to 0xF5 bytes
data[9] = _Count[1]; // Byte Count 0x07 to 0xF5 bytes
data[10] = 6; // Reference Type
byte[] _FileNum = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)fileNumber));
data[11] = _FileNum[0]; // File Number Hi
data[12] = _FileNum[1]; // File Number Lo
byte[] _RecordNum = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder(10000));
data[13] = _RecordNum[0]; // Record Number Hi
data[14] = _RecordNum[1]; // Record Number Lo
byte[] _RecordLength = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)recordLength));
data[15] = _RecordLength[0]; // Record Length Hi
data[16] = _RecordLength[1]; // Record Length Lo
return data;
}
这是回复:
[0,0,0,0,187,189,1,20,186,68,97,116,101,44,84,105,109,101,44,67,97,115,101,95,84, 44,68,57,95,84,44,68,49,95,84,44,65,109,98,95,84,44,82,72,44,68,80,44,67,117,114 ,44,80,68,95,86,44,80,111,119,101,114,44,68,86,44,70,97,117,108,116,76,111,44,70 ,97,117,108,116,72,105,10,0,0,0,0,0,0,.....]
我希望这对任何使用 Modbus 和 C# 工作的人都有用。
关于c# - 如何使用 C# 实现 Modbus 功能 20?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38081714/