Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate CRC using this code?

Tags:

c

crc

I'm trying to get going radio communication between a device and my server. Data from the device looks like this:

fa-00-01-09-16-aa-00-14-10-01-01-00-01-16-ff-ff-ff-ff-ff-ff-cb-14

where last two bytes are CRC. Now I need to send reply to my device and calculate its CRC as well. Device's data sheet doesn't say much and it only provides C function to calculate it, but I have a hard time understanding what should I feed to this function

unsigned int CRC_Check(unsigned char *ucCRC_Buf, unsigned char ucBufLength)
{
    unsigned int uiX, uiY, uiCRC;
    unsigned char ucStart = 0;
    uiCRC = 0xFFFF; //set all 1

    if (ucBufLength <= 0 || ucStart > ucBufLength)
    {
        uiCRC = 0;
    }
    else
    {
        ucBufLength += ucStart;

        for (uiX = (unsigned int)ucStart; uiX < ucBufLength; uiX++)
        {
            uiCRC = (unsigned int)(uiCRC ^ ucCRC_Buf[uiX]);

            for (uiY = 0; uiY <= 7; uiY++)
            {
                if((uiCRC & 1) != 0)
                    uiCRC = (unsigned int)((uiCRC >> 1)^0xA001);
                else
                    uiCRC = (unsigned int)(uiCRC >> 1);
            }
        }
    }

    return uiCRC;
}

Data sheet also says "CRC check is conducted on the data packet excluding the start code & check code" that means first byte (0xFA) and last two bytes (the CRC).

Now I'm trying to understand what it expects as unsigned char *ucCRC_Buf and unsigned char ucBufLength. From my main I'm trying to do:

unsigned int crc = CRC_Check("00010916aa0014100101000116ffffffffffff",38);
printf("%d\n", crc);

Which is same string as in the beginning (without the first and last two bytes) and I'm expecting CB14 (hex). But it gives different number (54016 (dec) which is D300 (hex)).

Any idea what I'm doing wrong?

like image 810
muliku Avatar asked Aug 15 '17 10:08

muliku


People also ask

How do I manually calculate CRC?

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.

What is a CRC code?

A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to digital data. Blocks of data entering these systems get a short check value attached, based on the remainder of a polynomial division of their contents.

How do you calculate CRC errors?

CRC Error Checking - No Errors Upon reception, an entire received codeword R(x) = "message + crc" can be checked simply by dividing R(x)/P(x) using the same generating polynomial. If the remainder after division equals zero, then no error was found.


2 Answers

Probably you have to pass the bytes themselves, not their hex-representation.

Change

unsigned int crc=CRC_Check("00010916aa0014100101000116ffffffffffff",38);

to

unsigned int crc=CRC_Check("\x00\x01\x09\x16\xaa\x00\x14\x10\x01\x01\x00\x01\x16\xff\xff\xff\xff\xff\xff", 19);

Note that there are only 19 bytes. (Thanks @alk)

like image 185
alain Avatar answered Sep 28 '22 06:09

alain


The data server is sending is assumed in Hexadecimal format.

You are passing a string to function which is giving you wrong results.

Correct way to verify is:

unsigned char data[] = {0x00,0x01,0x09,0x16,0xaa,0x00,0x14,0x10,0x01,0x01,0x00,0x01,0x16,0xff,0xff,0xff,0xff,0xff,0xff}

unsigned int CRC = CRC_Check(&data[0],19);
like image 39
Vagish Avatar answered Sep 28 '22 07:09

Vagish