modbustcp的通讯

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace WindowsFormsApp1
{
public class InovancePLCClient : IDisposable
{
private TcpClient _tcpClient;
private NetworkStream _stream;
private string _ipAddress;
private int _port;

    public InovancePLCClient(string ip, int port = 502)
    {
        _ipAddress = ip;
        _port = port;
        Connect();
    }

    private void Connect()
    {
        _tcpClient = new TcpClient();
        _tcpClient.Connect(IPAddress.Parse(_ipAddress), _port);
        _stream = _tcpClient.GetStream();
        _stream.ReadTimeout = 1000; // 设置超时时间
    }

    public void Dispose()
    {
        _stream?.Close();
        _tcpClient?.Close();
    }


    public ushort[] ReadHoldingRegisters(ushort startAddress, ushort numRegisters)
    {
        // 构造请求报文
        byte[] request = new byte[12];
        // 事务标识符(示例使用固定值)
        request[0] = 0x00;
        request[1] = 0x01;
        // 协议标识符(Modbus TCP固定为0)
        request[2] = 0x00;
        request[3] = 0x00;
        // 长度字段(后续字节数)
        request[4] = 0x00;
        request[5] = 0x06; // 6字节剩余
                           // 单元标识符(通常为1)
        request[6] = 0x01;
        // 功能码
        request[7] = 0x03;
        // 起始地址(大端)
        BitConverter.GetBytes(startAddress).CopyTo(request, 8);
        Array.Reverse(request, 8, 2);
        // 寄存器数量(大端)
        BitConverter.GetBytes(numRegisters).CopyTo(request, 10);
        Array.Reverse(request, 10, 2);

        // 发送请求
        _stream.Write(request, 0, request.Length);

        // 接收响应
        byte[] responseHeader = new byte[9];
        _stream.Read(responseHeader, 0, 9);

        // 检查功能码是否一致
        if (responseHeader[7] != 0x03)
            throw new Exception("Invalid response function code.");

        // 读取数据部分
        int dataLength = responseHeader[8];
        byte[] data = new byte[dataLength];
        _stream.Read(data, 0, dataLength);

        // 解析数据(每个寄存器2字节)
        ushort[] result = new ushort[numRegisters];
        for (int i = 0; i < numRegisters; i++)
        {
            result[i] = BitConverter.ToUInt16(data, i * 2);
            // Modbus为大端序,需根据实际情况处理字节序
            Array.Reverse(data, i * 2, 2);
        }

        return result;
    }


    public bool[] ReadCoils(ushort startAddress, ushort numCoils)
    {
        // 构造请求报文
        byte[] request = new byte[12];
        // 事务标识符(示例使用固定值)
        request[0] = 0x00;
        request[1] = 0x03;
        // 协议标识符(Modbus TCP固定为0)
        request[2] = 0x00;
        request[3] = 0x00;
        // 长度字段(后续字节数)
        request[4] = 0x00;
        request[5] = 0x06; // 6字节剩余
                           // 单元标识符(通常为1)
        request[6] = 0x01;
        // 功能码
        request[7] = 0x01;
        // 起始地址(大端)
        BitConverter.GetBytes(startAddress).CopyTo(request, 8);
        Array.Reverse(request, 8, 2);
        // 线圈数量(大端)
        BitConverter.GetBytes(numCoils).CopyTo(request, 10);
        Array.Reverse(request, 10, 2);

        // 发送请求
        _stream.Write(request, 0, request.Length);

        // 接收响应
        byte[] responseHeader = new byte[9];
        _stream.Read(responseHeader, 0, 9);

        // 检查功能码是否一致
        if (responseHeader[7] != 0x01)
            throw new Exception("Invalid response function code.");

        // 读取数据部分
        int dataByteCount = responseHeader[8];
        byte[] data = new byte[dataByteCount];
        _stream.Read(data, 0, dataByteCount);

        // 解析线圈状态
        bool[] result = new bool[numCoils];
        for (int i = 0; i < numCoils; i++)
        {
            int byteIndex = i / 8;
            int bitIndex = i % 8;
            byte mask = (byte)(1 << bitIndex);
            result[i] = (data[byteIndex] & mask) != 0;
        }

        return result;
    }


    public void WriteSingleRegister(ushort address, ushort value)
    {
        byte[] request = new byte[12];
        // 事务标识符
        request[0] = 0x00;
        request[1] = 0x02;
        // 协议标识符
        request[2] = 0x00;
        request[3] = 0x00;
        // 长度字段
        request[4] = 0x00;
        request[5] = 0x06;
        // 单元标识符
        request[6] = 0x01;
        // 功能码
        request[7] = 0x06;
        // 地址(大端)
        BitConverter.GetBytes(address).CopyTo(request, 8);
        Array.Reverse(request, 8, 2);
        // 值(大端)
        BitConverter.GetBytes(value).CopyTo(request, 10);
        Array.Reverse(request, 10, 2);

        _stream.Write(request, 0, request.Length);

        // 读取响应(写入操作响应与请求相同)
        byte[] response = new byte[12];
        _stream.Read(response, 0, 12);
    }


}

}

posted @ 2025-04-02 19:56  脐橙qc  阅读(47)  评论(0)    收藏  举报