TheBestPlayer
TheBestPlayer

Reputation: 404

Clarification regarding CRC16 calculation

I am trying to calculate CRC for the first time. I have read a few pages that explain what is crc and how to calculate. Mainly this : https://www.fatalerrors.org/a/implementation-of-crc-checksum-c-crc16-as-an-example.html

I have a code that calculates CRC16

uint16_t CalCrc(uint16_t crc_initial, uint8_t* buf,uint16_t len,uint16_t POLY)
{
    unsigned int byte;
    unsigned char k;
    unsigned short ACC,TOPBIT;
    unsigned short remainder = crc_initial;
    TOPBIT = 0x8000;
    for (byte = 0; byte < len; ++byte)
    {
        ACC = buf[byte];
        remainder ^= ACC;
        printf("new remainder = %u \n",remainder);
        for (k = 8; k > 0; --k)
        {
            if (remainder & TOPBIT)
            {
                remainder = remainder << 1;
                remainder = remainder ^ POLY;
            }
            else
            {
                remainder = (remainder << 1);
            }
        }
    }
    remainder = remainder^0x0000;
    printf("result remainder = %02X \n",remainder);
    return remainder;
}

and I call it my main.c:

    uint8_t crc_buf[5] = {0x05,0x03,0x04,0x08,0x04};
    CalCrc(0xffff,crc_buf,5,0x1021);

The result is:

result remainder = BDD5

As you can see from my function call, I pass 0xffff as initial crc value and 0x1021 as polynomial.

I am trying to confirm if my calculation is correct with some online crc calculators such as: http://www.sunshine2k.de/coding/javascript/crc/crc_js.html https://crccalc.com/

According to the initial and polynomial values that I use, the result should be: enter image description here

Could someone help me understand what is wrong here? Thanks in advance.

Upvotes: 0

Views: 959

Answers (1)

Ian Abbott
Ian Abbott

Reputation: 17513

You are missing a bit shift in the calculation. Change:

        ACC = buf[byte];

to:

        ACC = (unsigned)buf[byte] << 8;

Compare with this C# example code from Sunshine's Understanding and implementing CRC (Cyclic Redundancy Check) calculation:

public static ushort Compute_CRC16_Simple(byte[] bytes)
{
    const ushort generator = 0x1021; /* divisor is 16bit */
    ushort crc = 0; /* CRC value is 16bit */

    foreach (byte b in bytes)
    {
        crc ^= (ushort(b << 8); /* move byte into MSB of 16bit CRC */

        for (int i = 0; i < 8; i++)
        {
            if ((crc & 0x8000) != 0) /* test for MSB = bit 15 */
            {
                crc = (ushort((crc << 1) ^ generator);
            }
            else
            {
                crc <<= 1;
            }
        }
    }

    return crc;
}

It uses a different initial value to your function, but note the line that XORs the byte into the MSB of the 16-bit CRC:

        crc ^= (ushort(b << 8); /* move byte into MSB of 16bit CRC */

Upvotes: 2

Related Questions