我想实现CRC8生成器。CRC8-ATM工作正常。然而,当使用CRC8-MAXIM的多项式时,计算结果不同。我是不是计算错了?
==============================
CRC8-ATM
dat: "AB" = 01000001 01000010
ply: 0x107 = 100000111
res: 0x87
==============================
01000001 01000010 00000000
1000001 11
----------------------------
10000010 00000000
10000011 1
----------------------------
1 1000000
1 00000111
----------------------------
my_res: 10000111 => 0x87 (OK)
==============================
CRC8-MAXIM
dat: "AB" = 01000001 01000010
ply: 0x131 = 100110001
res: 0xA5
==============================
01000001 01000010 00000000
1001100 01
----------------------------
1101 00000010 00000000
1001 10001
----------------------------
100 10001010 00000000
100 110001
----------------------------
1001110 00000000
1001100 01
----------------------------
10 01000000
10 0110001
----------------------------
my_res : 00100010 => 0x22 (Must be 0xA5)
有关计算结果,请参阅下面的网站。
https://crccalc.com
如果有人熟悉CRC8的实现,请提供帮助。
是的。
常规CRC-8和CRC-8/MAXIM具有不同的RefIn
和RefOut
配置:
RefIn
参数指示数据字节在使用前是否应反转- CCD_ 4参数指示在应用最终CCD_
下面是一段计算CRC8算法的代码:
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
uint8_t uint8_reverse(uint8_t val)
{
uint8_t ret = 0;
for (size_t i = 0; i < 8; i++)
{
if (val & 0x80)
{
ret |= (1 << i);
}
val <<= 1;
}
return ret;
}
uint8_t crc8(uint8_t const * data, size_t data_size, uint8_t poly, uint8_t init,
bool refin, bool refout, uint8_t xor_out)
{
uint8_t crc = init;
for (size_t i = 0; i < data_size; i++)
{
crc = crc ^ (refin ? uint8_reverse(data[i]) : data[i]);
for (size_t j = 0; j < 8; j++)
{
if (crc & 0x80)
{
crc = (crc << 1) ^ poly;
}
else
{
crc <<= 1;
}
}
}
return (refout ? uint8_reverse(crc) : crc) ^ xor_out;
}
int main(void)
{
printf("--- Check data ---n");
const uint8_t check[9] = "123456789";
printf("crc8: 0x%02xn", crc8(check, 9, 0x07, 0x00, 0, 0, 0x00));
printf("crc8-cdma2000: 0x%02xn", crc8(check, 9, 0x9b, 0xff, 0, 0, 0x00));
printf("crc8-darc: 0x%02xn", crc8(check, 9, 0x39, 0x00, 1, 1, 0x00));
printf("crc8-itu: 0x%02xn", crc8(check, 9, 0x07, 0x00, 0, 0, 0x55));
printf("crc8-maxim: 0x%02xn", crc8(check, 9, 0x31, 0x00, 1, 1, 0x00));
printf("--- 'AB' data ---n");
const uint8_t ab_data[2] = "AB";
printf("crc8: 0x%02xn", crc8(ab_data, 2, 0x07, 0x00, 0, 0, 0x00));
printf("crc8-itu: 0x%02xn", crc8(ab_data, 2, 0x07, 0x00, 0, 0, 0x55));
printf("crc8-maxim: 0x%02xn", crc8(ab_data, 2, 0x31, 0x00, 1, 1, 0x00));
return 0;
}
它输出:
--- Check data ---
crc8: 0xf4
crc8-cdma2000: 0xda
crc8-darc: 0x15
crc8-itu: 0xa1
crc8-maxim: 0xa1
--- 'AB' data ---
crc8: 0x87
crc8-itu: 0xd2
crc8-maxim: 0xa5
请注意,大多数时候RefIn
和RefOut
具有相同的值,并且代码优化是可能的(,即避免所有字节反转操作(。
如@lrntgr所述,CRC-8/MAXIM定义反映了输入位和结果CRC位。用反映的输入和输出重新进行记法:
==============================
CRC8-MAXIM
dat: "AB" reflected = 10000010 01000010
ply: 0x131 = 100110001
res: 0xA5
==============================
10000010 01000010 00000000
10011000 1
----------------------------
11010 11000010 00000000
10011 0001
----------------------------
1001 11010010 00000000
1001 10001
----------------------------
1011010 00000000
1001100 01
----------------------------
10110 01000000
10011 0001
----------------------------
101 01010000
100 110001
----------------------------
1 10010100
1 00110001
----------------------------
my_res : 10100101 => reflected 10100101 = 0xA5
对于这个特定的例子,反射的0xA5
就是0xA5
!因此,不幸的是,你看不到需要对《儿童权利公约》进行最后反思。但是,确实如此。再举一个例子来看看。
同样如前所述,实际计算不需要反映输入和输出位,而是可以通过反映多项式并向下而不是向上移位来具有完全相同的效果。代码是:
unsigned crc8maxim(unsigned char const *dat, size_t len) {
unsigned crc = 0;
for (size_t i = 0; i < len; i++) {
crc ^= dat[i];
for (unsigned k = 0; k < 8; k++)
crc = crc & 1 ? (crc >> 1) ^ 0x8c : crc >> 1;
}
return crc;
}
其中0x8c
是0x31
的反映,不包括x8的多项式位。