生成CRC6的代码段未提供正确的值。 代码段中可能是什么问题?
SPI_CRC6 = X6 + X4 + X3 + X + 1
初始种子值为0x3F
输入数据:24位。
一些经过测试的样本值:(不是来自代码片段)
24b input: 0xAE0000, CRC6: 0x11
24b input: 0x950055, CRC6: 0x22
/* CRC6 calculation */
Uint16 crc2(Uint32 datin)
{
Uint16 byte_idx, bit_idx, crc = (0x3F << 2);//CRC_INITSEED = 0x3f
/* byte by byte starting from most significant (3-2-1) */
for (byte_idx = 3; byte_idx >= 1; byte_idx--)
{
/* XOR-in new byte from left to right */
crc ^= ((datin >> (byte_idx << 3)) & 0x000000FF);
/* bit by bit for each byte */
for (bit_idx = 0; bit_idx < 8; bit_idx++)
{
crc = crc << 1 ^ (crc & 0x80 ? (0x5B << 2) : 0);//CRC Polynom: 0x5B
}
}
return (crc >> 2 & 0x3F); /*restore two bit offset */
}
答案 0 :(得分:0)
代码应将输入移位16、8、0位时将其移位24、16、8位。解决此问题(并同时简化代码)的一种方法是将移位计数用作循环参数。
该代码还一次处理输入的8位。这会导致整个代码神秘地移位2。一次处理6位更为自然。在这种情况下,代码需要将输入移位18、12、6、0位。
所以我会这样写代码:
/* CRC6 calculation */
Uint16 crc2(Uint32 datin)
{
int input_shift;
Uint16 bit_idx, crc = 0x3F; //CRC seed = 0x3F
/* 6 bits at a time starting from most significant */
for (input_shift = 18; input_shift >= 0; input_shift -= 6)
{
/* XOR-in new data from left to right */
crc ^= (datin >> input_shift) & 0x3F;
/* bit by bit for each chunk */
for (bit_idx = 0; bit_idx < 6; bit_idx++)
{
crc <<= 1;
crc ^= (crc & 0x40) ? 0x5B : 0; //CRC polynomial: 0x5B
}
}
return crc & 0x3F; //return the 6-bit CRC
}
答案 1 :(得分:0)
user3386109的答案显示了代码的正确版本,但是在这种情况下,无需将数据分成6位字段。
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
uint16_t crc1(uint32_t datin)
{
int i;
uint32_t crc = datin ^ (0x3f << 18);
for (i = 0; i < 24; i++)
crc = (crc << 1) ^ ((crc & 0x800000) ? (0x5B << 18) : 0);
return crc >> 18;
}
以下示例假定二进制补码,使用(-0)= 0x00000000或(-1)= 0xffffffff作为掩码,以避免使用条件代码(三次?:)。请注意,对于上面的示例,优化的编译器也可能会使用数学运算来避免使用条件代码(Visual Studio会这样做)。
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
uint16_t crc1(uint32_t datin)
{
int i;
uint32_t crc = datin ^ (0x3f << 18);
for (i = 0; i < 24; i++)
crc = (crc << 1) ^ ((-(crc >> 23)) & (0x5B << 18));
return crc >> 18;
}
掩盖技巧常被编译器使用,一般顺序为:
... ;eax is zero or non-zero
neg eax ;sets borrow bit if eax != 0
sbb eax,eax ;eax = 0x00000000 or 0xffffffff
and eax,... ;use eax as mask