modubs的TCP数据协议

发布时间 2023-09-13 18:00:00作者: 世人皆萌

参考:C#实现MODBUS TCP 通信 第二章 (程序内实现) - 『编程语言区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

只要了解这个modubs的数据格式

常用的命令

功能码(16进制)    功能说明
0x01                          读取输出线圈              1
0x02                          读取输入线圈              2
0x03                          读取保持寄存器           3
0x04                          读取输入寄存器           4
0x05                          写入单个线圈              5
0x06                          写入单个寄存器            6
0x0F                          写入多个线圈               16
0x10                          写入多个寄存器            10

modubs数据协议格式

1. ModbusRtu的报文格式如下(PDU):
第一部分:从站地址,占1个字节
第二部分:功能码,占1个字节
第三部分:数据部分,占N个字节
第四部分:校验部分,CRC校验,占2个字节

2. ModbusAscii的报文格式如下:
第一部分:开始字符(:)
第二部分:从站地址,占2个字节
第三部分:功能码,占2个字节
第四部分:数据部分,占N个字节
第五部分:校验部分,LRC校验,占2个字节
第六部分:结束字符(CR LF)

3. ModbusTcp的报文格式如下:
第一部分:事务处理标识符,占2个字节
第二部分:协议标识符,占2个字节
第三部分:长度,占2个字节
第四部分:单元标识符,占1个字节
第五部分:功能码,占1个字节
第六部分:数据部分,占N个字节

修改modbus数据的格式(tcp)

请求内容:00 0B 00 00 00 06 06 01 00 02 00 08
事务处理标识(2字节):00 0B
协议标识符(2字节):00 00
长度(2字节):00 06
单元标识符(1字节):01
功能码(1字节):06
数据地址(2字节):00 02 
数据内容(2字节):00 08
响应内容:00 0B 00 00 00 06 06 01 00 02 00 08
事务处理标识(2字节):00 0B
协议标识符(2字节):00 00
长度(2字节):00 06
单元标识符(1字节):01
功能码(1字节):06
数据地址(2字节):00 02
数据内容(2字节):00 08

 代码实现

 //拼接
 List<byte> SendCommand = new List<byte>();
 //事物处理标识符
 SendCommand.AddRange(new byte[] { 0x00, 0x0B });
 //协议标识符
 SendCommand.AddRange(new byte[] { 0x00, 0x00 });
 //长度
 SendCommand.AddRange(new byte[] { 0x00, 0x06 });
 //单元标识符
 SendCommand.Add(0x01);
 ////功能码
 //SendCommand.Add(0x03);
 //功能码
 SendCommand.Add(0x06);


 ////起始地址
 //SendCommand.Add((byte)(start / 256));
 //SendCommand.Add((byte)(start % 256));
 ////结束地址-长度
 //SendCommand.Add((byte)(length / 256));
 //SendCommand.Add((byte)(length % 256));

 ////起始地址
 //SendCommand.AddRange(new byte[] { 0x00, 0x00 });
 ////结束地址-长度
 //SendCommand.AddRange(new byte[] { 0x00, 0x0A });

 //起始地址
 SendCommand.AddRange(new byte[] { 0x00, 0x01 });
 //具体数据
 SendCommand.AddRange(new byte[] { 0x00, 0x12 });


 var sendData = Encoding.Default.GetString(SendCommand.ToArray());
 Task.Factory.StartNew(new Action(() =>
 {
     Thread.Sleep(1000);
     _client.SendData(sendData);
 }));

返回的结果处理

 private void HandelByte(byte[] buffer)
 {
     int count = buffer.Count();
     if (buffer[7] == 0x03)//读取多个
     {
         int length = buffer[8] / 2;
         if (count == 9 + 2 * length)
         {
             ShowData(buffer, length);
         }
     }
     else if (buffer[7] == 0x06)//写入单个寄存器
     {
         //解析
         ushort[] data = new ushort[1];
         data[0] = BitConverter.ToUInt16(new byte[] { buffer[11], buffer[10] }, 0);
         Console.WriteLine(data);
     }
 }

 /// <summary>
 /// 
 /// </summary>
 /// <param name="buffer"></param>
 /// <param name="length"></param>
 /// <param name="j"></param>
 private void ShowData(byte[] buffer, int length)
 {
     //解析
     ushort[] data = new ushort[length];
     for (int i = 0; i < data.Length; i++)
     {
         data[i] = BitConverter.ToUInt16(new byte[] { buffer[9 + 2 * i + 1], buffer[9 + 2 * i] }, 0);
     }
     Console.WriteLine(data);
 }

效果图(这样就修改好了一个地址数据)