Search code examples
ccrc

How to calculate CRC using this code?


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?


Solution

  • 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)