上位机通过模块链接plc

报文格式

读报文: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();

 

posted @ 2022-10-20 18:03  我不是白菜啊  阅读(160)  评论(0)    收藏  举报