通讯协议时需要添加CRC冗余校验码,一般根据已存在的码生成,这里是先高位校验后低位校验,不同机器所需命令有所不同,可以自己调整
/// <summary>
/// CRC16_Modbus效验
/// </summary>
/// <param name="byteData">要进行计算的字节数组</param>
/// <returns>计算后的数组</returns>
public static byte[] ToModbus(byte[] byteData)
{
byte[] CRC = new byte[2];
UInt16 wCrc = 0xFFFF;
for (int i = 0; i < byteData.Length; i++)
{
wCrc ^= Convert.ToUInt16(byteData[i]);
for (int j = 0; j < 8; j++)
{
if ((wCrc & 0x0001) == 1)
{
wCrc >>= 1;
wCrc ^= 0xA001;//异或多项式
}
else
{
wCrc >>= 1;
}
}
}
CRC[1] = (byte)((wCrc & 0xFF00) >> 8);//高位在后
CRC[0] = (byte)(wCrc & 0x00FF); //低位在前
return CRC;
}
在使用时可以优先一步转换获取设备码+地址码+功能码,不同设备对应命令不同
注意,设备编码是十六进制位,即'10'对应的为'0A'而非'10'
添加空格是因为不加机器识别不出来
for (int i = 1; i <= count; i++)
{
//查询功能命令
string functionOrder = " 03 00 00 00 02 C4 0B ";
//设备编号转十六进制并截取后两位
string address = i.ToString("X6").Substring(4, 2);
//地址码和功能码组合成不带CRC校验的命令码,再去获取对应CRC码
string commandPro = address + functionOrder;
//设备编号转btye[]
byte[] address16 = HexStringToByteArray(commandPro);
//获取设备编码的CRC校验码
byte[] addressCRC = ToModbus(address16);
//CRC校验码转string
string crcpro = byteToHexStr(addressCRC);
//获取CRC校验码的低字节位
string crclow = crcpro.Substring(0, 2);
//获取CRC校验码的高字节位
string crchigh = crcpro.Substring(2, 2);
//增加空格转为有效CRC码
string crc = crclow + " " + crchigh;
//地址码+功能码+CRC校验码组成最终查询命令码
string command = address + functionOrder + crc;
Send(command);
Thread.Sleep(2000);
}