我正在计算 CRC16-CCITT/KERMIT,以便检查 C# Winforms 应用程序和微控制器(PSoC5LP/Arm Cortex-M3)之间 64 字节数据包传输的数据完整性。我很接近,但只是没有完全让 CRC 计算在两者之间对齐,并且很难弄清楚原因。我计算 CRC 的示例数据包是:
02 03 01 02 03 04 05 07 08 09 0A 0B 00 00 06 0E 0C 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
在我的 Winforms 应用程序和这个在线 CRC 计算器中,这个数据包的 CRC 为 0x4D8C
由于这些排列,我假设 C# 计算中的计算是合法的。无论如何,这是代码。从这个页面中提取,唯一的变化是我硬编码了多项式(0x8408):
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;
}
}
}
现在,问题在于为微控制器提供了一个有效的 CRC16-CCITT/KERMIT 计算器功能,该功能将为该数据包生成相同的 CRC。
这是我目前拥有的(从这个答案中提取):
uint16_t crc16k(uint16_t crc, uint8_t *mem, uint8_t len) {
uint8_t *data = mem;
if (data == NULL){
return 0;
}
crc = ~crc;
crc &= 0xffff;
while (len--) {
crc ^= *data++;
for (uint8_t k = 0; k < 8; k++)
crc = crc & 1 ? (crc >> 1) ^ 0x8408 : crc >> 1;
}
crc ^= 0xFFFF;
return crc;
}
我这样称呼它:
uint16_t crc_calc = crc16k(0x0000, message_in, 64);
这是我得到一些有趣的地方。该数据包是 64 字节,但实际上(对于此数据包),只有前 29 个字节是我正在使用的数据。其余的只是填充以满足 64 个字节。当我在 WinForms 端计算 CRC 时,看起来它正在使用所有 64 个字节,包括填充。当我在微控制器端做同样的事情时,我得到了 0xE918 的结果。奇怪的是,如果我将长度参数限制为我感兴趣的 29 个字节,我会得到 0x4C8B,它非常接近我正在寻找的 0x4D8C。我还注意到,在我使用的在线计算器中,它声称输出的 XOR 应该是 0x0000。我在输出上使用 XORs 0xFFFF 的 C 函数。将其更改为 0x0000(并处理所有 64 个字节)给我 0x16E7。
所以我不确定问题出在哪里。这是我第一次使用 CRC,所以我可能会遗漏一些明显的东西。有任何想法吗?
预先感谢您的帮助!让我知道我是否应该提供任何其他信息。