CRC-16 and/or 帧校验序列
CRC-16 and/or Frame Check Sequence
我有一个从串行端口读取 7E0302403F387E 的传入数据包。
开始和结束标志为7E,FCS/CRC为3F38,数据为030240。FCS根据RFC 1662中指定的算法计算。https://www.rfc-editor.org/rfc/rfc1662#appendix-A
这是我用来为 030240 生成 FCS 的代码:
static byte[] HexToBytes(string input)
{
byte[] result = new byte[input.Length / 2];
for (int i = 0; i < result.Length; i++)
{
result[i] = Convert.ToByte(input.Substring(2 * i, 2), 16);
}
return result;
}
public static class Crc16
{
const ushort polynomial = 0x8408;
static readonly ushort[] table = new ushort[256];
public static ushort ComputeChecksum(byte[] bytes)
{
ushort crc = 0;
for (int i = 0; i < bytes.Length; ++i)
{
byte index = (byte)(crc ^ bytes[i]);
crc = (ushort)((crc >> 8) ^ table[index]);
}
return crc;
}
static Crc16()
{
ushort value;
ushort temp;
for (ushort i = 0; i < table.Length; ++i)
{
value = 0;
temp = i;
for (byte j = 0; j < 8; ++j)
{
if (((value ^ temp) & 0x0001) != 0)
{
value = (ushort)((value >> 1) ^ polynomial);
}
else
{
value >>= 1;
}
temp >>= 1;
}
table[i] = value;
}
}
}
我是这样称呼它的:
//string input = "00 03 00 02 04 00";
string input = "030240";
var bytes = HexToBytes(input);
string hexe = Crc16.ComputeChecksum(bytes).ToString("x2");
我应该得到 3F38 的 FCS,但我得到的是 9ED0。我做错了什么?
编辑 1:
我正在从串行端口读取 ~[=16=]\u0003[=16=]\u0002\u0004[=16=]?8~
。我可以将其转换为 7E-03-02-40-3F-38-7E
或 7e-5c-30-5c-75-30-30-30-33-5c-30-5c-75-30-30-30-32-5c-75-30-30-30-34-5c-30-3f-38-7e
。第一个太短,第二个太长。我应该得到 10 个字节。有什么建议吗?
编辑 2:
我正在使用 ASCII_To_Hex 将 ~[=16=]\u0003[=16=]\u0002\u0004[=16=]?8~
转换为 7E-03-02-40-3F-38-7E
public string ASCII_To_Hex(string ASCII)
{
char[] charValues = dataIN.ToCharArray();
string hexOutput = "";
foreach (char _eachChar in charValues)
{
// Get the integral value of the character.
int value = Convert.ToInt32(_eachChar);
// Convert the decimal value to a hexadecimal value in string form.
hexOutput += String.Format("{0:X}", value);
// to make output as your eg
// hexOutput +=" "+ String.Format("{0:X}", value);
}
return hexOutput;
}
我可以在此处进行哪些更改以正确解密传入的数据包?
编辑 3:
我根据马克的建议做了以下修改:
public static class Crc16
{
const ushort polynomial = 0x1021;
static readonly ushort[] table = new ushort[256];
public static ushort ComputeChecksum(byte[] bytes)
{
ushort crc = 0xffff;
for (int i = 0; i < bytes.Length; ++i)
{
byte index = (byte)(crc ^ bytes[i]);
crc = (ushort)((crc >> 8) ^ table[index]);
}
return (ushort)~crc;
}
static Crc16()
{
ushort value;
ushort temp;
for (ushort i = 0; i < table.Length; ++i)
{
value = 0;
temp = i;
for (byte j = 0; j < 8; ++j)
{
if (((value ^ temp) & 0x0001) != 0)
{
value = (ushort)((value >> 1) ^ polynomial);
}
else
{
value >>= 1;
}
temp >>= 1;
}
table[i] = value;
}
}
}
我是这样称呼它的:
string hex = "00-03-00-02-04-00";
hex = hex.Replace("-", "");
var bytes = HexToBytes(hex);
string hexe = Crc16.ComputeChecksum(bytes).ToString("X2");
我得到的是 FO93
而不是 389B
根据链接的附录,CRC的初始值为0xffff
,不是0,需要与0xffff
异或得到FCS放入数据包。
然而,这仍然不适用于您的示例数据包。我只能猜测您的示例数据包未正确提取或识别。
更新:
根据下面的 OP 评论和一些推论,消息中的 实际 数据是 "~\x00\x03\x00\x02\x04\x00\x9b\x38~"
。由于某种原因,OP 遗漏了三个零字节,并且 OP 以将一个字节作为问号遮盖的方式打印出来。
现在 CRC 正确计算为0x389b
,存储在消息little-endian 中为0x9b
0x38
。为此,您必须应用我上面关于初始值和最终异或的评论。
我有一个从串行端口读取 7E0302403F387E 的传入数据包。
开始和结束标志为7E,FCS/CRC为3F38,数据为030240。FCS根据RFC 1662中指定的算法计算。https://www.rfc-editor.org/rfc/rfc1662#appendix-A
这是我用来为 030240 生成 FCS 的代码:
static byte[] HexToBytes(string input)
{
byte[] result = new byte[input.Length / 2];
for (int i = 0; i < result.Length; i++)
{
result[i] = Convert.ToByte(input.Substring(2 * i, 2), 16);
}
return result;
}
public static class Crc16
{
const ushort polynomial = 0x8408;
static readonly ushort[] table = new ushort[256];
public static ushort ComputeChecksum(byte[] bytes)
{
ushort crc = 0;
for (int i = 0; i < bytes.Length; ++i)
{
byte index = (byte)(crc ^ bytes[i]);
crc = (ushort)((crc >> 8) ^ table[index]);
}
return crc;
}
static Crc16()
{
ushort value;
ushort temp;
for (ushort i = 0; i < table.Length; ++i)
{
value = 0;
temp = i;
for (byte j = 0; j < 8; ++j)
{
if (((value ^ temp) & 0x0001) != 0)
{
value = (ushort)((value >> 1) ^ polynomial);
}
else
{
value >>= 1;
}
temp >>= 1;
}
table[i] = value;
}
}
}
我是这样称呼它的:
//string input = "00 03 00 02 04 00";
string input = "030240";
var bytes = HexToBytes(input);
string hexe = Crc16.ComputeChecksum(bytes).ToString("x2");
我应该得到 3F38 的 FCS,但我得到的是 9ED0。我做错了什么?
编辑 1:
我正在从串行端口读取 ~[=16=]\u0003[=16=]\u0002\u0004[=16=]?8~
。我可以将其转换为 7E-03-02-40-3F-38-7E
或 7e-5c-30-5c-75-30-30-30-33-5c-30-5c-75-30-30-30-32-5c-75-30-30-30-34-5c-30-3f-38-7e
。第一个太短,第二个太长。我应该得到 10 个字节。有什么建议吗?
编辑 2:
我正在使用 ASCII_To_Hex 将 ~[=16=]\u0003[=16=]\u0002\u0004[=16=]?8~
转换为 7E-03-02-40-3F-38-7E
public string ASCII_To_Hex(string ASCII)
{
char[] charValues = dataIN.ToCharArray();
string hexOutput = "";
foreach (char _eachChar in charValues)
{
// Get the integral value of the character.
int value = Convert.ToInt32(_eachChar);
// Convert the decimal value to a hexadecimal value in string form.
hexOutput += String.Format("{0:X}", value);
// to make output as your eg
// hexOutput +=" "+ String.Format("{0:X}", value);
}
return hexOutput;
}
我可以在此处进行哪些更改以正确解密传入的数据包?
编辑 3:
我根据马克的建议做了以下修改:
public static class Crc16
{
const ushort polynomial = 0x1021;
static readonly ushort[] table = new ushort[256];
public static ushort ComputeChecksum(byte[] bytes)
{
ushort crc = 0xffff;
for (int i = 0; i < bytes.Length; ++i)
{
byte index = (byte)(crc ^ bytes[i]);
crc = (ushort)((crc >> 8) ^ table[index]);
}
return (ushort)~crc;
}
static Crc16()
{
ushort value;
ushort temp;
for (ushort i = 0; i < table.Length; ++i)
{
value = 0;
temp = i;
for (byte j = 0; j < 8; ++j)
{
if (((value ^ temp) & 0x0001) != 0)
{
value = (ushort)((value >> 1) ^ polynomial);
}
else
{
value >>= 1;
}
temp >>= 1;
}
table[i] = value;
}
}
}
我是这样称呼它的:
string hex = "00-03-00-02-04-00";
hex = hex.Replace("-", "");
var bytes = HexToBytes(hex);
string hexe = Crc16.ComputeChecksum(bytes).ToString("X2");
我得到的是 FO93
而不是 389B
根据链接的附录,CRC的初始值为0xffff
,不是0,需要与0xffff
异或得到FCS放入数据包。
然而,这仍然不适用于您的示例数据包。我只能猜测您的示例数据包未正确提取或识别。
更新:
根据下面的 OP 评论和一些推论,消息中的 实际 数据是 "~\x00\x03\x00\x02\x04\x00\x9b\x38~"
。由于某种原因,OP 遗漏了三个零字节,并且 OP 以将一个字节作为问号遮盖的方式打印出来。
现在 CRC 正确计算为0x389b
,存储在消息little-endian 中为0x9b
0x38
。为此,您必须应用我上面关于初始值和最终异或的评论。