1

我一直在使用这个 Modbus TCP 库(https://github.com/stephanstricker/modbusTCP/tree/master/ModbusTCP/ModbusTCP)和这个文档来参考函数 20 (http://www .modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf)。问题是它不支持功能代码 20(阅读一般参考/文件)。现在我只是想创建自己的函数来处理它,但是我得到的响应是一个 10 和 1 的两字节数组。

这是我尝试使用的请求标头:

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,...]

更新:

我将我的请求标头修改为此。

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,..]

4

1 回答 1

1

我想到了。我所做的更新创建了正确的标题,但是文件可能已损坏,所以我决定读取另一个文件并且我成功了。

这是我的代码:

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# 的人有用。

于 2016-06-28T21:39:45.267 回答