Search code examples
c++cembeddedcrccrc16

Issues with calculating CRC16/MCRF4XX


I would like some help as I seem to be unable to calculate the CRC for a single byte, let alone an array of bytes.

Below is the test code that I have been trying to get work. Please note that I used the code from this post, and the example with the array of chars works, but I need to be able to adapt this to work for an array of uint8_t.

When going through the fundamentals of CRC, this seems like it should work but I may be mistaken.

I have been trying to validate the function by checking the outputted remainder (crc) using this site.

If someone could kindly identify where the issue is coming round which is leading to the wrong CRC value being calculated, and educate me as to why this is happening, that would be highly appreciated!

#include <cstdint>
#include <iostream>

// Below 2 functions take from 
// https://stackoverflow.com/questions/59486262/issues-calculating-crc16-mcrf4xx-for-more-than-1-byte

int16_t Utils_CRC16_MCRF4XX( uint16_t Crc, uint8_t Byte )
{
    Crc ^= Byte ;

    for( uint8_t i = 0; i < 8; i++ )
    {
        Crc = (Crc & 0x0001) != 0 ? (Crc >> 1) ^ 0x8408 : 
                                    Crc >> 1 ;
    }

    return Crc ;
}

uint16_t crc( uint8_t* pData, uint32_t Len )
{
    uint16_t Crc = 0xffff;

    for( uint32_t i = 0; i < Len; i++ )
    {
        Crc = Utils_CRC16_MCRF4XX( Crc, pData[i] );
    }
    return (Crc);
}

int main()
{
    int8_t val1 = 30;
    int8_t val2 = 30;

    // Arbitrary Test Message
    uint8_t message[] = 
    {
        (uint8_t)54
    };

    /*
    // Sample Test Message (Actually what I intend to transmit)
    uint8_t message[] = 
    {
        (uint8_t)250,
        (uint8_t)7,
        (uint8_t)21,
        (uint8_t)2,
        (uint8_t)2,
        (uint8_t)val1,
        (uint8_t)val2
    };
    */

    //uint8_t test[] = "123456789";

    uint16_t remainder = crc(message, sizeof(message));
    // Expected DEC: 28561
    // Actual DEC: 23346

    std::cout << "CRC: " << remainder << std::endl;

    return 0;
}

Solution

  • If you do this:

        uint8_t test[] = "123456789";
    
        uint16_t remainder = crc(test, sizeof(test)-1);
    

    then you get the expected result, 28561.

    You need to subtract 1 from sizeof(test) to exclude the terminating 0.