上一章,我们对MODBUS 的报文已经有初步了解,本章就在程序内来具体实现,我先建立了一个MODBUS 方法类,类中包含有常用的读写方法,以及数据处理方法,由于我是用在实际生产中,所以对寄存器的值有限制,只能是正数,所以还有数据转换方法,可以作为参考,类的具体代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace ModbusTCPDemo
{
public class ModbusTCP
{
private Socket socket = null;
public bool Connect(string ip, int port)
{
//实例化Socket
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
socket.Connect(IPAddress.Parse(ip), port);
return true;
}
catch (Exception)
{
return false;
}
}
public void DisConnect()
{
if (socket != null)
{
socket.Close();
}
}
//读取寄存器
public ushort[] ReadKeeepReg(ushort start, ushort length)
{
//拼接
List<byte> SendCommand = new List<byte>();
//事物处理标识符
SendCommand.AddRange(new byte[] { 0x00, 0x00 });
//协议标识符
SendCommand.AddRange(new byte[] { 0x00, 0x00 });
//长度
SendCommand.AddRange(new byte[] { 0x00, 0x06 });
//单元标识符
SendCommand.Add(0x01);
//功能码
SendCommand.Add(0x03);
//起始地址
SendCommand.Add((byte)(start / 256));
SendCommand.Add((byte)(start % 256));
//结束地址-长度
SendCommand.Add((byte)(length / 256));
SendCommand.Add((byte)(length % 256));
//发送
socket.Send(SendCommand.ToArray());
//接收
byte[] buffer = new byte[512];
int count = socket.Receive(buffer, SocketFlags.None);
//验证-截取
byte[] result = new byte[count];
Array.Copy(buffer, 0, result, 0, count);
if (count == 9 + 2 * length)
{
if (result[7] == 0x03)
{
//解析
ushort[] data = new ushort[length];
for (int i = 0; i < data.Length; i++)
{
data[i] = BitConverter.ToUInt16(new byte[] { result[9 + 2 * i + 1], result[9 + 2 * i] },0);
}
return data;
}
return null;
}
return null;
}
//写入单个寄存器
public List<byte> WriteInputRge(short start, short writedata)
{
//拼接
List<byte> SendCommand = new List<byte>();
//事物处理标识符
SendCommand.AddRange(new byte[] { 0x00, 0x00 });
//协议标识符
SendCommand.AddRange(new byte[] { 0x00, 0x00 });
//长度
SendCommand.AddRange(new byte[] { 0x00, 0x06 });
//单元标识符
SendCommand.Add(0x01);
//功能码
SendCommand.Add(0x06);
//寄存器地址
SendCommand.Add((byte)(start / 256));
SendCommand.Add((byte)(start % 256));
//具体数据
SendCommand.Add((byte)(writedata / 256));
SendCommand.Add((byte)(writedata % 256));
//发送
socket.Send(SendCommand.ToArray());
//接收
byte[] buffer = new byte[512];
int count = socket.Receive(buffer, SocketFlags.None);
//验证-截取
byte[] result = new byte[count];
Array.Copy(buffer, 0, result, 0, count);
List<byte> ReceiveCommand = result.ToList();
if (ReceiveCommand[0] == SendCommand[0])
{
return ReceiveCommand;
}
return null;
}
//写入多个寄存器
public List<byte> BatchWriteInputRge(short start, short length,short[] data)
{
//拼接
List<byte> SendCommand = new List<byte>();
//事物处理标识符
SendCommand.AddRange(new byte[] { 0x00, 0x00 });
//协议标识符
SendCommand.AddRange(new byte[] { 0x00, 0x00 });
//长度
SendCommand.Add((byte)((9 + (length - 1) * 2) / 256));
SendCommand.Add((byte)((9 + (length - 1) * 2) % 256));
//单元标识符
SendCommand.Add(0x01);
//功能码
SendCommand.Add(0x10);
//寄存器地址
SendCommand.Add((byte)(start / 256));
SendCommand.Add((byte)(start % 256));
//寄存器个数
SendCommand.Add((byte)(length / 256));
SendCommand.Add((byte)(length % 256));
//写字节个数
SendCommand.Add((byte)(data.Length*2));
for (int i = 0; i < data.Length; i++)
{
SendCommand.Add((byte)(data[i] / 256));
SendCommand.Add((byte)(data[i] % 256));
}
//发送
socket.Send(SendCommand.ToArray());
//接收
byte[] buffer = new byte[512];
int count = socket.Receive(buffer, SocketFlags.None);
//验证-截取
byte[] result = new byte[count];
Array.Copy(buffer, 0, result, 0, count);
List<byte> ReceiveCommand = result.ToList();
if (ReceiveCommand[0] == SendCommand[0])
{
return ReceiveCommand;
}
return null;
// 00 00 00 00 00 0B 01 10 00 00 00 02 04 00 99 11 55
}
//数据拆分方法,将一个32位int 转换成4个8位int
public int[] Int32BitTo8Bit(int i)
{
int[] ints = new int[4];
if (i > 0)
{
int n1 = i & 0xffff;
int n2 = i >> 16;
ints[0] = n1 & 0xff;
ints[1] = n1 >> 8;
ints[2] = n2 & 0xff;
ints[3] = n2 >> 8;
int ii = (((ints[3] << 8) + ints[2]) << 16) + ((ints[1] << 8) + ints[0]);
return ints;
}
return null;
}
}
实现步骤:
1.建立连接
2.调用方法
ModbusTCP modbusTCP = new ModbusTCP(); //实例化ModbusTCP 类
if (modbusTCP.Connect("127.0.0.1", 502))//调用连接方法
{
int[] data_int = modbusTCP.Int32BitTo8Bit(Convert.ToInt32(zcl));
short[] data_short = new short[data_int.Length];
for (int i = 0; i < data_int.Length; i++)
{
data_short[i] = (short)data_int[i];
}
System.Collections.Generic.List<byte> val = modbusTCP.BatchWriteInputRge(0, (short)data_short.Length, data_short);
if (val != null)
{
string s="";
for (int i = 0; i < val.Count; i++)
{
s +=" " + val[i].ToString();
}
Console.WriteLine("写入成功返回:"+s);
}
else
{
Console.WriteLine("写入失败!");
}
![图片[1]-C#实现MODBUS TCP 通信 第二章 (程序内实现)-民间安全 - 白帽子黑客在线学习安全交流平台](https://www.4x45.com/wp-content/uploads/2021/12/11-1.webp)
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END