Search code examples
ccrc

How to calculate crc8 in C?


I have seen multiple implementation of crc8 implementation in C, but I am unable to figure out for polynomial(x8,x5,x4,1) i.e. 0x31 and initialization 0xFF.

Also reflect input = False, reflect output = False and final XOR = 0x00.

I tried several of them, and I expect such that CRC(0x00)=0xAC and CRC(0xBEEF)=0x92.

I have seen similar implementations, but nothing really worked out. I saw the exact functionality in here http://www.sunshine2k.de/coding/javascript/crc/crc_js.html where I could give initialization, reflect input, reflect output, and final XOR. But can somebody point to me implementation in C. I do understand that initially we need to give crc as 0xFF, but nothing worked out for me so far.

Please find the sample code that I tried attached:

#include <stdio.h>
#include <stdint.h>

uint8_t crc8(uint16_t input);

int main()
{
    uint8_t temp1;
    uint16_t temp2 = 0xBEEF;

    printf("CRC input is 0x%X\n", temp2);

    temp1 = crc8(temp2);

    printf("CRC output is 0x%X\n", temp1);

    return 0;
}

uint8_t crc8(uint16_t input)
{
    uint8_t crc[8] = { };
    uint8_t i;
    uint8_t inv;
    uint8_t output = 0;

    for(i = 0; i < 16; i++)
    {
        inv = ((((input >> i) & 1) ^ crc[7]) & 1);

        crc[7] = (crc[6] & 1);
        crc[6] = (crc[5] & 1);
        crc[5] = (crc[4] ^ inv & 1);
        crc[4] = (crc[3] ^ inv & 1);
        crc[3] = (crc[2] & 1);
        crc[2] = (crc[1] & 1);
        crc[1] = (crc[0] & 1);
        crc[0] = (inv & 1);
    }

    for(i = 0; i < 8; i++){
        output |= ((crc[i] << i) & (1 << i));
    }


    return output;
}

I am seeing

CRC input is 0xBEEF
CRC output is 0x2 //instead of 0x92

Solution

  • Assuming your running on a PC or other little endian processor, temp2 is stored in memory as {0xEF, 0xBE}. Unoptimized example code (doesn't use a table). For a faster version, the inner loop using j could be replaced with a 256 byte table lookup: crc = table[crc ^ data[i]];

    #include <stdio.h>
    
    typedef unsigned char uint8_t;
    
    uint8_t gencrc(uint8_t *data, size_t len)
    {
        uint8_t crc = 0xff;
        size_t i, j;
        for (i = 0; i < len; i++) {
            crc ^= data[i];
            for (j = 0; j < 8; j++) {
                if ((crc & 0x80) != 0)
                    crc = (uint8_t)((crc << 1) ^ 0x31);
                else
                    crc <<= 1;
            }
        }
        return crc;
    }
    
    int main()
    {
    uint8_t data[8] = {0xBE,0xEF,0,0,0,0,0,0};
    uint8_t crc;
        crc = gencrc(data, 2);   /* returns 0x92 */
        printf("%1x\n", crc);
        crc = gencrc(data+2, 1); /* returns 0xac */
        printf("%1x\n", crc);
        return 0;
    }