报文格式
读报文:01 03 E0 0D 00 01 AB CD
01是设备地址默认都是01;03是功能码,参考modbus功能码;E0 0D 是操作的PLC地址,是由10进制的PLC地址转换为16进制得到,此处对应的是57357;00 01对应的是读取长度;AB CD 是根据前面信息得到的校验码
C#上位机,代码开发,组建读取报文
List<byte> data = new List<byte>(255);
data.Add(Convert.ToByte(1));//路由
data.Add(Convert.ToByte(3));//功能码
data.AddRange(BitConverter.GetBytes((ushort)0).Reverse().ToArray());//地址
data.AddRange(BitConverter.GetBytes((ushort)1).Reverse().ToArray());//数量
byte[] dataBuff = CRC.ToModbusCRC16Byte(data.ToArray(), true);
data.AddRange(dataBuff);//校验码
return data.ToArray();
此处需要注意地址和数量的转换,因为C#里面的数字默认是32位int,需要转换为ushort,不然报文会多出几位
写单个寄存器报文:01 06 E0 0D 00 23 6E 10
01是设备地址默认都是01;06是功能码;E0 0D 是操作的PLC地址;00 23对应的是写入的数据;6E 10是根据前面信息得到的校验码
写多个寄存器报文:01 0F 00 00 00 02 04 00 01 00 02 23 AE
01是设备地址,0;0F是功能码;00 00 是起始地址;00 02是寄存器数量;04是长度;001是第一个值;002是第二个值;23 AE是校验码
C#上位机,代码开发,组建报文
List<byte> data = new List<byte>(255);
data.Add(Convert.ToByte(route));//设备地址
data.Add(Convert.ToByte(fCode));//功能码
data.AddRange(StringUtils.DataConvertToBytes(add));//地址
if (fCode == 6 || fCode == 16)//寄存器一个数量=两个长度
{
data.AddRange(StringUtils.DataConvertToBytes((ushort)(len / 2)));//寄存器个数
data.Add(Convert.ToByte(len));//字节
}
else
{
data.AddRange(StringUtils.DataConvertToBytes(len)); //寄存器个数
data.Add(Convert.ToByte(Math.Ceiling(Convert.ToDecimal(len) / 8)));
}
byte[] b = new byte[data.Count + toValue.Length];
Array.Copy(data.ToArray(), 0, b, 0, data.Count);
Array.Copy(toValue, 0, b, data.Count, toValue.Length);
byte[] dataBuff = new byte[2];
dataBuff = CRC.ToModbusCRC16Byte(b, true);
data.AddRange(toValue);//数据
data.AddRange(dataBuff);//校验码
return data.ToArray();
标签:00,01,Convert,AddRange,上位,地址,plc,模块,data From: https://www.cnblogs.com/ThisYbc/p/16810790.html