这个CRC6片段给出了错误的结果

问题描述 投票:2回答:2

生成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 */
}
c crc
2个回答
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
}

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作为掩码来避免使用条件代码(tenary?:)。请注意,优化编译器也可以使用数学来避免上述示例的条件代码(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
© www.soinside.com 2019 - 2024. All rights reserved.