<>C# modbus TCP协议应用
<>协议简介
Modbus由MODICON公司(现施耐德公司)于1979年开发,是一种工业现场总线协议标准。主要分为了RTU,ASCII,TCP三种协议类型。本文我们只探讨C#
modbusTCP的应用。
modbusTcp协议采用master/slave模型。在modbus总线中是以"一主多从"关系存在的。通讯方式是主站发出请求(广播或者单播),从站收到请求后应答。
<>报文分析
请求 :19 15 00 00 00 06 01 03 05 4A 00 01 应答:19 15 00 00 00 05 01 03 02 11 22
请求: 19 15 为报文标识符,一般每次通信加1来表示区别不同报文 00 00 表示modbusTCP协议 00 06 表示后面的数据长度 01 从站号
03 功能码。 05 4A 读取数据的起始地址 00 01 读几位地址(读连续的地址) 应答: 19 15 为报文标识符 00 00
表示modbusTCP协议 00 05 表示后面的数据长度 01 从站号 03 功能码 02 表示读到的数据长度 11 22 表示读到的数据
不同于RTU协议,不需要进行CRC校验
功能码含义
01读线圈
05写单个线圈
0F写多个线圈
02读离散量输入
04读输入寄存器
03读保持寄存器
06写单个保持寄存器
10写多个保持寄存器
<>modbusTCP master实现
一般来说上位机作为客户端和主站进行连接
* 字符集 using System.Net; using System.Net.Sockets;
* tcp连接 string ip = "192.168.20.79"; int port = 502; // 创建socket var socket =
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //
建立连接 socket.Connect(new IPEndPoint(IPAddress.Parse(ip), port));
* 读保持寄存器和线圈 //拼接报文 public byte[] getReadCommand(ushort address, byte station,
byte funtion, ushort length) //寄存器地址 站号 功能码 寄存器长度 { byte[] buffer = new byte[12]
; buffer[0] = 0x19; buffer[1] = 0x12; //client发出的验证信息 buffer[2] = 0x00; buffer[3
] = 0x00; //表示tcp/ip的协议的modbus的协议 buffer[4] = 0x00; buffer[5] = 0x06;
//表示的是该字节以后的字节长度 buffer[6] = station; //站号 buffer[7] = funtion; //功能码 buffer[8]
= BitConverter.GetBytes(address)[1]; buffer[9] = BitConverter.GetBytes(address)[
0]; //寄存器地址 buffer[10] = BitConverter.GetBytes(length)[1]; buffer[11] =
BitConverter.GetBytes(length)[0]; //寄存器的长度 return buffer; } //发送报文 socket.Send(
buffer); //接收数据 byte[] write_done_recvBuffer = new byte[11]; socket.Receive(
write_done_recvBuffer, 0, write_done_recvBuffer.Length, SocketFlags.None);
5.写线圈和保持寄存器
public byte[] writeCommand(ushort address, byte station, byte funtion, byte[]
values) //寄存器地址 站号 功能码 寄存器长度 { byte[] buffer = new byte[10+ values.Length];
buffer[0] = 0x19; buffer[1] = 0xB2; //client发出的验证信息 buffer[2] = 0x00; buffer[3]
= 0x00; //表示tcp/ip的协议的modbus的协议 buffer[4] = BitConverter.GetBytes(4 + values.
Length)[1]; buffer[5] = BitConverter.GetBytes(4 + values.Length)[0];
//表示的是该字节以后的字节长度 buffer[6] = station; //站号 buffer[7] = funtion; //功能码 buffer[8]
= BitConverter.GetBytes(address)[1]; buffer[9] = BitConverter.GetBytes(address)[
0]; //寄存器地址 values.CopyTo(buffer, 10); return buffer; } //接收数据 byte[]
write_done_recvBuffer= new byte[20];// socket.Receive(write_done_recvBuffer, 0,
write_done_recvBuffer.Length, SocketFlags.None);