反向倒数CRC-8值的确认?
Confirmation of Reverse Reciprocal CRC-8 Value?
我花了很多时间来确认在两个设备之间的 ASCII 数据通信中使用的 CRC-8 算法的类型。我已经确认 CRC 是在文本字节的 0x02 开始 + 数据的下一个字节上计算的。我描述一个设备的接口设计文档指定使用初始值为 0xFF 的 0xEA 多项式。下面是一条捕获的消息的示例:
输入字节: 0x02 0x41
CRC 结果: b10011011 或 0x9B
进入这个问题,我对典型的 CRC 算法的内部工作原理知之甚少。最初,我尝试对输入字节进行手工计算,以在尝试代码解决方案之前确认我对算法的理解。这涉及将第一个输入字节与我的 0xFF 初始值进行异或,然后跳到第二个输入字节以继续进行异或运算。
我曾多次尝试通过典型的异或运算来确认 CRC,同时在每一步中将 MSB 移出寄存器,但我始终无法获得想要的结果。今天,我意识到 0xEA 多项式也被认为是 0xD5 多项式的倒数,隐含的 1+x^8 常用于 CRC-8 算法。这个事实如何改变我手动计算 CRC 的方式?我读过,在某些情况下,反向会导致算法右移而不是左移?
多项式为x^8+x^7+x^5+x^3+x^2+x+1 => 01AF位反转为x^8+x^7+x^6+x ^5+x^3+x+1 => 0x1EB。示例代码,其中条件 XOR 在移位后完成,因此 XOR 值为 0x1EB>>1 = 0xF5。可以使用 256 字节 table 查找来替换内部循环。
using System;
namespace crc8r
{
class Program
{
private static byte crc8r(byte[] bfr, int bfrlen)
{
byte crc = 0xff;
for (int j = 0; j < bfrlen; j++)
{
crc ^= bfr[j];
for (int i = 0; i < 8; i++)
// assumes twos complement math
crc = (byte)((crc>>1)^((0-(crc&1))&0xf5));
}
return crc;
}
static void Main(string[] args)
{
byte[] data = new byte[3] {0x02, 0x41, 0x00};
byte crc;
crc = crc8r(data, 2); // crc == 0x9b
Console.WriteLine("{0:X2}", crc);
data[2] = crc;
crc = crc8r(data, 3); // crc == 0x00
Console.WriteLine("{0:X2}", crc);
return;
}
}
}
关于 "EA",如果多项式在移位之前进行异或运算,则使用 0x1EB(或 0x1EA,因为位 0 将被移出并且无关紧要)。移位前的异或运算需要 9 位,或者 post 移位 OR 或 0x80 的异或运算,而移位后的异或运算仅需要 8 位。
移位前使用 0x1eb 的示例代码行:
crc = (byte)((crc^((0-(crc&1))&0x1eb))>>1);
我花了很多时间来确认在两个设备之间的 ASCII 数据通信中使用的 CRC-8 算法的类型。我已经确认 CRC 是在文本字节的 0x02 开始 + 数据的下一个字节上计算的。我描述一个设备的接口设计文档指定使用初始值为 0xFF 的 0xEA 多项式。下面是一条捕获的消息的示例:
输入字节: 0x02 0x41
CRC 结果: b10011011 或 0x9B
进入这个问题,我对典型的 CRC 算法的内部工作原理知之甚少。最初,我尝试对输入字节进行手工计算,以在尝试代码解决方案之前确认我对算法的理解。这涉及将第一个输入字节与我的 0xFF 初始值进行异或,然后跳到第二个输入字节以继续进行异或运算。
我曾多次尝试通过典型的异或运算来确认 CRC,同时在每一步中将 MSB 移出寄存器,但我始终无法获得想要的结果。今天,我意识到 0xEA 多项式也被认为是 0xD5 多项式的倒数,隐含的 1+x^8 常用于 CRC-8 算法。这个事实如何改变我手动计算 CRC 的方式?我读过,在某些情况下,反向会导致算法右移而不是左移?
多项式为x^8+x^7+x^5+x^3+x^2+x+1 => 01AF位反转为x^8+x^7+x^6+x ^5+x^3+x+1 => 0x1EB。示例代码,其中条件 XOR 在移位后完成,因此 XOR 值为 0x1EB>>1 = 0xF5。可以使用 256 字节 table 查找来替换内部循环。
using System;
namespace crc8r
{
class Program
{
private static byte crc8r(byte[] bfr, int bfrlen)
{
byte crc = 0xff;
for (int j = 0; j < bfrlen; j++)
{
crc ^= bfr[j];
for (int i = 0; i < 8; i++)
// assumes twos complement math
crc = (byte)((crc>>1)^((0-(crc&1))&0xf5));
}
return crc;
}
static void Main(string[] args)
{
byte[] data = new byte[3] {0x02, 0x41, 0x00};
byte crc;
crc = crc8r(data, 2); // crc == 0x9b
Console.WriteLine("{0:X2}", crc);
data[2] = crc;
crc = crc8r(data, 3); // crc == 0x00
Console.WriteLine("{0:X2}", crc);
return;
}
}
}
关于 "EA",如果多项式在移位之前进行异或运算,则使用 0x1EB(或 0x1EA,因为位 0 将被移出并且无关紧要)。移位前的异或运算需要 9 位,或者 post 移位 OR 或 0x80 的异或运算,而移位后的异或运算仅需要 8 位。
移位前使用 0x1eb 的示例代码行:
crc = (byte)((crc^((0-(crc&1))&0x1eb))>>1);