Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate crc8 in C?

Tags:

c

crc

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
like image 219
arnab dasgupta Avatar asked Aug 08 '18 17:08

arnab dasgupta


People also ask

How is CRC value calculated?

A CRC is pretty simple; you take a polynomial represented as bits and the data, and divide the polynomial into the data (or you represent the data as a polynomial and do the same thing). The remainder, which is between 0 and the polynomial is the CRC.

How does CRC checksum work?

CRC involves binary division of the data bits being sent by a predetermined divisor agreed upon by the communicating system. The divisor is generated using polynomials. So, CRC is also called polynomial code checksum. Before sending the message over network channels, the sender encodes the message using CRC.

What is a CRC polynomial?

A CRC is called an n-bit CRC when its check value is n bits long. For a given n, multiple CRCs are possible, each with a different polynomial. Such a polynomial has highest degree n, which means it has n + 1 terms. In other words, the polynomial has a length of n + 1; its encoding requires n + 1 bits.


1 Answers

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;
}
like image 136
rcgldr Avatar answered Oct 19 '22 22:10

rcgldr