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);
}
}
}

浙公网安备 33010602011771号