CRC common parameter model and C ා code implementation

Time:2020-12-5

catalog
  • parameter model
  • Algorithm implementation
    • CRC-32
    • CRC-32/MPEG-2
    • Table generation algorithm
  • reference material
  • Source code of this article

parameter model

CRC (cyclic redundancy check): is the most commonly used error checking code in the field of data communication. Its characteristic is that the length of information field and check field can be arbitrarily selected. Cyclic redundancy check (CRC) is a kind of data transmission error detection function. It calculates the polynomial of data and attaches the result to the frame. The receiving equipment also implements similar algorithm to ensure the correctness and integrity of data transmission.

CRC algorithm parameter model explanation:

  • NAME: parameter model name.
  • WIDTH: width, that is, the number of CRC bits.
  • POLY: abbreviation of the generated item, expressed in hexadecimal. For example, CRC-32 is 0x04c11db7, ignoring the highest “1”, that is, the complete generated item is 0x104c11db7.
  • INIT: This is the initialization preset value of the register (CRC) at the beginning of the algorithm, expressed in hexadecimal.
  • REFIN: of the data to be measuredEach byteWhether to reverse bitwise, true or false.
  • REFOUT: after calculation, before XOR output,The whole dataWhether to reverse bitwise, true or false.
  • XOROUT: the final CRC value is obtained after the calculated result is XOR with this parameter.

The common CRC parameter models are as follows:

CRC algorithm name Polynomial formula width polynomial Initial value Result XOR value Input reversal Output reversal
CRC-4/ITU x4 + x + 1 4 03 00 00 true true
CRC-5/EPC x5 + x3 + 1 5 09 09 00 false false
CRC-5/ITU x5 + x4 + x2 + 1 5 15 00 00 true true
CRC-5/USB x5 + x2 + 1 5 05 1F 1F true true
CRC-6/ITU x6 + x + 1 6 03 00 00 true true
CRC-7/MMC x7 + x3 + 1 7 09 00 00 false false
CRC-8 x8 + x2 + x + 1 8 07 00 00 false false
CRC-8/ITU x8 + x2 + x + 1 8 07 00 55 false false
CRC-8/ROHC x8 + x2 + x + 1 8 07 FF 00 true true
CRC-8/MAXIM x8 + x5 + x4 + 1 8 31 00 00 true true
CRC-16/IBM x16 + x15 + x2 + 1 16 8005 0000 0000 true true
CRC-16/MAXIM x16 + x15 + x2 + 1 16 8005 0000 FFFF true true
CRC-16/USB x16 + x15 + x2 + 1 16 8005 FFFF FFFF true true
CRC-16/MODBUS x16 + x15 + x2 + 1 16 8005 FFFF 0000 true true
CRC-16/CCITT x16 + x12 + x5 + 1 16 1021 0000 0000 true true
CRC-16/CCITT-FALSE x16 + x12 + x5 + 1 16 1021 FFFF 0000 false false
CRC-16/X25 x16 + x12 + x5 + 1 16 1021 FFFF FFFF true true
CRC-16/XMODEM x16 + x12 + x5 + 1 16 1021 0000 0000 false false
CRC-16/DNP x16 + x13 + x12 + x11 + x10 + x8 + x6 + x5 + x2 + 1 16 3D65 0000 FFFF true true
CRC-32 x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 32 04C11DB7 FFFFFFFF FFFFFFFF true true
CRC-32/MPEG-2 x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 32 04C11DB7 FFFFFFFF 00000000 false false

Note:The polynomial selected by CRC algorithm will affect the ability of CRC algorithm to check errorsIt is not allowed to define polynomials at will, but to choose a general CRC polynomial.

Algorithm implementation

It is only given hereCRC-32CRC-32/MPEG-2The two algorithms have the same polynomial, but the parameter model is very different.
By comparing the implementation code of the two algorithms, it is easy to write other parameter model CRC algorithm with look-up table method, and then use itTable generation algorithmGenerate the corresponding table.

CRC-32

The code is as follows:

public static class Crc32
{
    //CRC calculation table (depending on whether the polynomial and input are reversed)
    static readonly uint[] crcTable = new uint[256] { 
        0x00000000u, 0x77073096u, 0xee0e612cu, 0x990951bau, 0x076dc419u, 0x706af48fu, 0xe963a535u, 0x9e6495a3u, 
        0x0edb8832u, 0x79dcb8a4u, 0xe0d5e91eu, 0x97d2d988u, 0x09b64c2bu, 0x7eb17cbdu, 0xe7b82d07u, 0x90bf1d91u,             
        0x1db71064u, 0x6ab020f2u, 0xf3b97148u, 0x84be41deu, 0x1adad47du, 0x6ddde4ebu, 0xf4d4b551u, 0x83d385c7u, 
        0x136c9856u, 0x646ba8c0u, 0xfd62f97au, 0x8a65c9ecu, 0x14015c4fu, 0x63066cd9u, 0xfa0f3d63u, 0x8d080df5u, 
        0x3b6e20c8u, 0x4c69105eu, 0xd56041e4u, 0xa2677172u, 0x3c03e4d1u, 0x4b04d447u, 0xd20d85fdu, 0xa50ab56bu,
        0x35b5a8fau, 0x42b2986cu, 0xdbbbc9d6u, 0xacbcf940u, 0x32d86ce3u, 0x45df5c75u, 0xdcd60dcfu, 0xabd13d59u, 
        0x26d930acu, 0x51de003au, 0xc8d75180u, 0xbfd06116u, 0x21b4f4b5u, 0x56b3c423u, 0xcfba9599u, 0xb8bda50fu, 
        0x2802b89eu, 0x5f058808u, 0xc60cd9b2u, 0xb10be924u, 0x2f6f7c87u, 0x58684c11u, 0xc1611dabu, 0xb6662d3du, 
        0x76dc4190u, 0x01db7106u, 0x98d220bcu, 0xefd5102au, 0x71b18589u, 0x06b6b51fu, 0x9fbfe4a5u, 0xe8b8d433u, 
        0x7807c9a2u, 0x0f00f934u, 0x9609a88eu, 0xe10e9818u, 0x7f6a0dbbu, 0x086d3d2du, 0x91646c97u, 0xe6635c01u,
        0x6b6b51f4u, 0x1c6c6162u, 0x856530d8u, 0xf262004eu, 0x6c0695edu, 0x1b01a57bu, 0x8208f4c1u, 0xf50fc457u, 
        0x65b0d9c6u, 0x12b7e950u, 0x8bbeb8eau, 0xfcb9887cu, 0x62dd1ddfu, 0x15da2d49u, 0x8cd37cf3u, 0xfbd44c65u, 
        0x4db26158u, 0x3ab551ceu, 0xa3bc0074u, 0xd4bb30e2u, 0x4adfa541u, 0x3dd895d7u, 0xa4d1c46du, 0xd3d6f4fbu, 
        0x4369e96au, 0x346ed9fcu, 0xad678846u, 0xda60b8d0u, 0x44042d73u, 0x33031de5u, 0xaa0a4c5fu, 0xdd0d7cc9u, 
        0x5005713cu, 0x270241aau, 0xbe0b1010u, 0xc90c2086u, 0x5768b525u, 0x206f85b3u, 0xb966d409u, 0xce61e49fu,
        0x5edef90eu, 0x29d9c998u, 0xb0d09822u, 0xc7d7a8b4u, 0x59b33d17u, 0x2eb40d81u, 0xb7bd5c3bu, 0xc0ba6cadu, 
        0xedb88320u, 0x9abfb3b6u, 0x03b6e20cu, 0x74b1d29au, 0xead54739u, 0x9dd277afu, 0x04db2615u, 0x73dc1683u, 
        0xe3630b12u, 0x94643b84u, 0x0d6d6a3eu, 0x7a6a5aa8u, 0xe40ecf0bu, 0x9309ff9du, 0x0a00ae27u, 0x7d079eb1u,
        0xf00f9344u, 0x8708a3d2u, 0x1e01f268u, 0x6906c2feu, 0xf762575du, 0x806567cbu, 0x196c3671u, 0x6e6b06e7u, 
        0xfed41b76u, 0x89d32be0u, 0x10da7a5au, 0x67dd4accu, 0xf9b9df6fu, 0x8ebeeff9u, 0x17b7be43u, 0x60b08ed5u,
        0xd6d6a3e8u, 0xa1d1937eu, 0x38d8c2c4u, 0x4fdff252u, 0xd1bb67f1u, 0xa6bc5767u, 0x3fb506ddu, 0x48b2364bu, 
        0xd80d2bdau, 0xaf0a1b4cu, 0x36034af6u, 0x41047a60u, 0xdf60efc3u, 0xa867df55u, 0x316e8eefu, 0x4669be79u, 
        0xcb61b38cu, 0xbc66831au, 0x256fd2a0u, 0x5268e236u, 0xcc0c7795u, 0xbb0b4703u, 0x220216b9u, 0x5505262fu,
        0xc5ba3bbeu, 0xb2bd0b28u, 0x2bb45a92u, 0x5cb36a04u, 0xc2d7ffa7u, 0xb5d0cf31u, 0x2cd99e8bu, 0x5bdeae1du, 
        0x9b64c2b0u, 0xec63f226u, 0x756aa39cu, 0x026d930au, 0x9c0906a9u, 0xeb0e363fu, 0x72076785u, 0x05005713u,
        0x95bf4a82u, 0xe2b87a14u, 0x7bb12baeu, 0x0cb61b38u, 0x92d28e9bu, 0xe5d5be0du, 0x7cdcefb7u, 0x0bdbdf21u, 
        0x86d3d2d4u, 0xf1d4e242u, 0x68ddb3f8u, 0x1fda836eu, 0x81be16cdu, 0xf6b9265bu, 0x6fb077e1u, 0x18b74777u,
        0x88085ae6u, 0xff0f6a70u, 0x66063bcau, 0x11010b5cu, 0x8f659effu, 0xf862ae69u, 0x616bffd3u, 0x166ccf45u,
        0xa00ae278u, 0xd70dd2eeu, 0x4e048354u, 0x3903b3c2u, 0xa7672661u, 0xd06016f7u, 0x4969474du, 0x3e6e77dbu,
        0xaed16a4au, 0xd9d65adcu, 0x40df0b66u, 0x37d83bf0u, 0xa9bcae53u, 0xdebb9ec5u, 0x47b2cf7fu, 0x30b5ffe9u,
        0xbdbdf21cu, 0xcabac28au, 0x53b39330u, 0x24b4a3a6u, 0xbad03605u, 0xcdd70693u, 0x54de5729u, 0x23d967bfu,
        0xb3667a2eu, 0xc4614ab8u, 0x5d681b02u, 0x2a6f2b94u, 0xb40bbe37u, 0xc30c8ea1u, 0x5a05df1bu, 0x2d02ef8du
    };

    public static readonly string Name = "CRC-32";

    public static uint Compute(byte[] buffer) 
    {
        if (buffer == null)
        {
            Throw new argumentexception ("parameter exception, please check the caller");
        }
        return Compute(buffer, 0, buffer.Length);
    }

    public static uint Compute(byte[] buffer, int offset, int length)
    {
        if(!((buffer != null) && (offset >= 0) && (length >= 0) && (offset <= buffer.Length - length)))
        {
            Throw new argumentexception ("parameter exception, please check the caller");
        }

        //Initial value of register
        uint crc32= 0xffffffffU; 

        while (--length >= 0)
        {
            //Look up table operation (depending on whether width and output are reversed)
            crc32 = crcTable[(crc32 ^ buffer[offset++]) & 0xFF] ^ (crc32 >> 8);
        }
        //Result XOR
        crc32 ^= 0xffffffffU;
        return crc32;
    }
}

The tests are as follows:

byte[] data = new byte[] { 0x31, 0x32, 0x33, 0x34,0x35,0x36,0x37,0x38,0x39 };
uint crc32 = Crc32.Compute(data);
byte[] crc32Ary = BitConverter.GetBytes(crc32);
string crc32Str = "";
for (int i = crc32Ary.Length-1; i >=0; i--)
{
    crc32Str += crc32Ary[i].ToString("X2");
}
Console.WriteLine(crc32Str);
Console.ReadLine();

Test results:

CBF43926

CRC-32/MPEG-2

The code is as follows:

public static class Crc32
{
    //CRC calculation table (depending on whether the polynomial and input are inverse)
    static readonly uint[] crcTable = new uint[256] {  
        0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
        0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
        0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
        0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
        0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
        0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
        0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
        0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
        0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
        0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
        0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
        0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
        0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
        0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
        0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
        0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
        0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
        0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
        0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
        0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
        0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
        0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
        0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
        0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
        0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
        0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
        0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
        0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
        0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
        0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
        0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
        0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
    };

    public static readonly string Name = "CRC-32/MPEG-2";

    public static uint Compute(byte[] buffer) 
    {
        if (buffer == null)
        {
            Throw new argumentexception ("parameter exception, please check the caller");
        }
        return Compute(buffer, 0, buffer.Length);
    }

    public static uint Compute(byte[] buffer, int offset, int length)
    {
        if (!((buffer != null) && (offset >= 0) && (length >= 0) && (offset <= buffer.Length - length)))
        {
            Throw new argumentexception ("parameter exception, please check the caller");
        }
        //Initial value of register
        uint crc32= 0xffffffffU;

        //Output inversion processing: 32 is the width of CRC check
        int ToRight = 32 - 8;
        ToRight = ToRight < 0 ? 0 : ToRight;

        while (--length >= 0)
        {
            //Look up table operation (depending on whether width and output are reversed)
            crc32 = crcTable[((crc32 >> ToRight) ^ buffer[offset++]) & 0xFF] ^ (crc32 << 8);                
        }

        //Result XOR processing
        crc32 ^= 0x00000000U;
        return crc32;
    }
}

The tests are as follows:

byte[] data = new byte[] { 0x31, 0x32, 0x33, 0x34,0x35,0x36,0x37,0x38,0x39 };
uint crc32 = Crc32.Compute(data);
byte[] crc32Ary = BitConverter.GetBytes(crc32);
string crc32Str = "";
for (int i = crc32Ary.Length-1; i >=0; i--)
{
    crc32Str += crc32Ary[i].ToString("X2");
}
Console.WriteLine(crc32Str);
Console.ReadLine();

Test results:

0376E6E7

Table generation algorithm

static UInt64[] PrecomputationTable = new UInt64[256];
static void CreateCrcTable(string Name,Int32 width, UInt64 polynomial, UInt64 initial, Boolean isInputReflected, Boolean isOutputReflected, UInt64 outputXor)
{
    If (width < 8 | width > 64) {throw new argumentoutofrangeexception ("width", "must be a multiple of 8 and be between 8 and 64. "); }

	for (var i = 0; i < PrecomputationTable.Length; i++) {
		var r = (UInt64) i;
		if (isInputReflected) {
			r = ReverseBits(r, width);
		} else if (width > 8) {
			r <<= width - 8;
		}

		var lastBit = 1ul << (width - 1);

		for (var j = 0; j < 8; j++) {
			if ((r & lastBit) != 0) {
				r = (r << 1) ^ polynomial;
			} else {
				r <<= 1;
			}
		}

		if (isInputReflected) {
			r = ReverseBits(r, width);
		}

		PrecomputationTable[i] = r;
	}

    //Print table
    StringBuilder sbr = new StringBuilder();
    sbr.Append(Name);
    sbr.AppendLine (the table of "" is as follows:);
    for (int i = 0; i < PrecomputationTable.Length; i++)
    {
        if (i % 5 == 0) sbr.AppendLine();
        sbr.Append("0x");        
        sbr.Append(string.Format("{0:x}", PrecomputationTable[i]).PadLeft(16,'0').Substring(16-width/4,width/4));                
        sbr.Append(",");
    }
    string tab = sbr.ToString();
    Console.WriteLine(tab);
    Console.ReadLine();
}
static UInt64 ReverseBits(UInt64 value, Int32 valueLength)
{
    UInt64 output = 0;
    for (var i = valueLength - 1; i >= 0; i--)
    {
        output |= (value & 1) << i;
        value >>= 1;
    }
    return output;
}

The tests are as follows:

//CreateCrcTable("CRC-32", 32, 0x04C11DB7, 0xFFFFFFFF, true, true, 0xFFFFFFFF);
//CreateCrcTable("CRC-32/MPEG-2", 32, 0x04C11DB7, 0xFFFFFFFF, false, false, 0x00000000);
//CreateCrcTable("CRC-16/XMODEM", 16, 0x1021, 0x0, false, false, 0x0);
CreateCrcTable("CRC-16/USB", 16, 0x8005, 0xffff, true, true, 0xffff);

reference material

CRC online computing — ip33.com
Crc32helper -. Net source code
crc——github

Source code of this article

Crcdemo (Baidu disk extract code: 4xt3)