我在为can消息实现CRC16时遇到了一些问题,我遵循了本网站给出的说明https://barrgroup.com/embedded-systems/how-to/crc-calculation-c-code和http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html#ch5,加上我在这里看到的其他含义(例如计算CRC16校验和的函数(。
我不明白它是如何处理的。我在这里的消息是字节形式的,例如char message[4] = {0x12, 0x34, 0x56, 0x78}
。当我经历第一个循环时,我只取第一个字节,将其移位8,然后计算remainder
,POLYNOME
为16 bits
。这意味着我们有0x1200
,我们用它进行第二个循环,这意味着我用存储在remainder
中的POLYNOME
进行XOR
,但我不太明白为什么这样做,尤其是当我看这段代码时,我的消息的2nd
、3rd
和4th
bytes
在某些时候应该通过POLYNOME
的8 first bits
获得XORed
,但它们根本没有经过。根据维基百科的解释https://en.wikipedia.org/wiki/Cyclic_redundancy_check多项式一次遍历整个消息,而不是逐字节遍历。我不知道这是如何一个字节一个字节地进行0x12345678
的CRC的。
uint16_t Compute_CRC16_Simple(char* message, int nbOfBytes)
{
uint16_t POLYNOME = 0xC599;
uint16_t remainder = 0;
for (int byte = 0;byte < nbOfBytes; byte++)
{
remainder ^= (message[byte] << 8);
for (int i = 0; i < 8; i++)
{
if (remainder & 0x8000)
{
remainder = (remainder << 1) ^ POLYNOME ;
}
else
{
remainder <<= 1;
}
}
}
return remainder;
}
我不明白它是如何处理的。
也许它将有助于描述8位数据的逐位操作:
crc[bit15] ^= data[bit7]
if(crc[bit15] == 1) crc = (crc << 1) ^ poly
else crc = crc << 1
crc[bit15] ^= data[bit6]
if(crc[bit15] == 1) crc = (crc << 1) ^ poly
else crc = crc << 1
...
crc[bit15] ^= data[bit0]
if(crc[bit15] == 1) crc = (crc << 1) ^ poly
else crc = crc << 1
请注意,if语句仅取决于crc[bit15]中的位值,因此与数据的XOR的固定部分可以在一个步骤中完成:
crc[bit15 .. bit8] ^= data[bit7 .. bit0]
if(crc[bit15] == 1) crc = (crc << 1) ^ poly
else crc = crc << 1
if(crc[bit15] == 1) crc = (crc << 1) ^ poly
else crc = crc << 1
...
if(crc[bit15] == 1) crc = (crc << 1) ^ poly
else crc = crc << 1
CRC的循环8次使用那些如果。。。则可以针对crc[bit15.bit8]中的所有256个可能值预先计算(移位+xor-poly(else(仅移位(,并将其存储在用于表查找的表中以将crc循环8次。