Search code examples
crccrc16

CRC-16 specific example for serial connection


While working with the following PDF, there is an example in

Section 4: CRC-16 Code and Example

(page 95 or 91) that shows a serial packet with a CRC16 value of 133 (LSB) and 24 (MSB).

However, I have tried different calculators, for example:

  1. Lammert
  2. Elaborate calculator
  3. CRC calc

but I cannot get the CRC16 values that the PDF indicates, regardless of the byte combination I use.

How can I correctly calculate the CRC16 in the example, preferably using one of these calculators? (otherwise, C/C++ code should work).

Thanks.


Solution

  • This particular CRC is CRC-16/ARC. crcany generates the code for this CRC, which includes this simple bit-wise routine:

    #include <stddef.h>
    #include <stdint.h>
    
    uint16_t crc16arc_bit(uint16_t crc, void const *mem, size_t len) {
        unsigned char const *data = mem;
        if (data == NULL)
            return 0;
        for (size_t i = 0; i < len; i++) {
            crc ^= data[i];
            for (unsigned k = 0; k < 8; k++) {
                crc = crc & 1 ? (crc >> 1) ^ 0xa001 : crc >> 1;
            }
        }
        return crc;
    }
    

    The standard interface is to do crc = crc16arc_bit(0, NULL, 0); to get the initial value (zero in this case), and then crc = crc16arc_bit(crc, data, len); with successive portions of the message to compute the CRC.

    If you do that on the nine-byte message in the appendix, {1, 2, 1, 0, 17, 3, 'M', 'O', 'C'}, the returned CRC is 0x1885, which has the least significant byte 133 in decimal and most significant byte 24 in decimal.

    Faster table-driven routines are also generated by crcany.

    If you give 01 02 01 00 11 03 4d 4f 43 as hex to Lammert Bies' calculator, the very first one, called "CRC-16" gives 0x1885.

    If you give 0102010011034d4f43 to crccalc.com and hit Calc-CRC16, the second line is CRC-16/ARC, with the result 0x1885.