使用字节数据的 CRC16 是如何工作的? (用于 CAN 总线实现)
How CRC16 using bytes data is woking ? (for CAN bus implementation)
我在为 can 消息实现 CRC16 时遇到了一些问题,我按照本网站给出的说明进行操作 https://barrgroup.com/embedded-systems/how-to/crc-calculation-c-code and http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html#ch5, plus other implention I have seen in here ( for example Function to Calculate a CRC16 Checksum)。
我不明白它是如何处理的。
我这里的消息是字节形式的,比如char message[4] = {0x12, 0x34, 0x56, 0x78}
。当我通过第一个循环时,我只取第一个字节,将其移动 8 并用 16 bits
的 POLYNOME
计算 remainder
。
这意味着我们有 0x1200
并且我们用它进行第二个循环,这意味着我用存储在 remainder
中的 POLYNOME
做了一个 XOR
但我没有不太明白为什么会这样,尤其是当我查看这段代码时,我的消息的 2nd
、3rd
和 4th
bytes
应该得到 XORed
POLYNOME
的 8 first bits
在某些时候根本没有经过它。
根据维基百科的解释 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;
}
I don't understand how it is processed.
也许描述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]中的位值,所以与数据异或的固定部分可以一步完成:
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
使用 if ... then (shift + xor poly) else (just shift) 循环 8 次 CRC 可以为 crc[bit15 .. bit8] 中的所有 256 个可能值预先计算,并存储在table 用于 table 查找以循环 CRC 8 次。
我在为 can 消息实现 CRC16 时遇到了一些问题,我按照本网站给出的说明进行操作 https://barrgroup.com/embedded-systems/how-to/crc-calculation-c-code and http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html#ch5, plus other implention I have seen in here ( for example Function to Calculate a CRC16 Checksum)。
我不明白它是如何处理的。
我这里的消息是字节形式的,比如char message[4] = {0x12, 0x34, 0x56, 0x78}
。当我通过第一个循环时,我只取第一个字节,将其移动 8 并用 16 bits
的 POLYNOME
计算 remainder
。
这意味着我们有 0x1200
并且我们用它进行第二个循环,这意味着我用存储在 remainder
中的 POLYNOME
做了一个 XOR
但我没有不太明白为什么会这样,尤其是当我查看这段代码时,我的消息的 2nd
、3rd
和 4th
bytes
应该得到 XORed
POLYNOME
的 8 first bits
在某些时候根本没有经过它。
根据维基百科的解释 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;
}
I don't understand how it is processed.
也许描述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]中的位值,所以与数据异或的固定部分可以一步完成:
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
使用 if ... then (shift + xor poly) else (just shift) 循环 8 次 CRC 可以为 crc[bit15 .. bit8] 中的所有 256 个可能值预先计算,并存储在table 用于 table 查找以循环 CRC 8 次。