CRC calculations

Back to MiscEl main page Write a message to author

Contents

  • General info
  • Code for crc8 calculations
  • - crc8 bit, normal
  • - crc8 bit, inverted/reversed/reflected
  • - crc8 byte, normal
  • - crc8 byte, inverted/reversed/reflected
  • Code for crc16 calculations
  • - crc16 bit, normal
  • - crc16 bit, inverted/reversed/reflected
  • - crc16 byte normal
  • - crc16 byte, inverted/reversed/reflected
  • Code for crc32 calculations
  • - crc32 bit, normal
  • - crc32 bit, inverted/reversed/reflected
  • - crc32 byte, normal
  • - crc32 byte, inverted/reversed/reflected
  • Notes
  • General info


    This page shows how to code a crc calculation, both normal and reversed (reflected) code is shown. All coding examples are in Delphi pascal, I belive this is very readable code, and easy to translate to other languages.
    Using the reverse version of the code, with the inverted polynom, will give same result as reversing the data, before calculating the crc and reversing the final result.
    CRC code are usual made in two performance categories, the low performance algorithms with bit handling and the high performance table drive algorithm with byte handling. The table can either be pregenerated and saved together with the code or generated on the fly. On small microcontrollers with limited ram, it is usual best to pregenerate the table and save it in rom/flash memory.
    The table will always be 256 word large, the word size depends on the crc algorithms used (crc8=8 bit, crc16=16 bit, crc32=32 bit), but sometimes it may be a good idea to use a larger size, to get word aligment on the processor used.

    Both the bit and the byte based routines are show here.
    The bit routines can be used directly, but the byte routines need to initialize the table first. This is done with the bit routine from the "GenerateTable..." routine.
    I.e. to use the byte based routines your need to include a pregenerated table or the bit routine to generate the table. The Crc and Checksum page can be used to pregenerate the table.

    If this code is implemented on small processors, it is recommended to reduce the variable and table size from 32 bits to 8 bits for crc8 and 16 bits for crc16. It will also improve performance to use pointers to data, and avoid copying data around.

    Use Crc and Checksum page in MiscEl to verify your code.


    CRC8

    The following polynomial are used:
    NormalInverted/reversed/reflected
    $07$e0
    $31$8C

    CRC8 bit, normal

    function crc8(Buffer:String;Polynom,Initial:Cardinal):Cardinal;
    var
      i,j                   : Integer;
    begin
    Result:=Initial;
    for i:=1 to Length(Buffer) do begin
      Result:=Result xor ord(buffer[i]);
      for j:=0 to 7 do begin
        if (Result and $80)<>0 then Result:=(Result shl 1) xor Polynom
        else Result:=Result shl 1;
        end;
      end;
    Result:=Result and $ff;
    end;
    

    CRC8 bit, inverted/reversed/reflected

    Remember to use corresponding polynomial values.
    function crc8reverse(Buffer:String;Polynom,Initial:Cardinal):Cardinal;
    var
      i,j                   : Integer;
    begin
    Result:=Initial;
    for i:=1 to Length(Buffer) do begin
      Result:=Result xor ord(buffer[i]);
      for j:=0 to 7 do begin
        if (Result and $01)<>0 then Result:=(Result shr 1) xor Polynom
        else Result:=Result shr 1;
        end;
      end;
    end;
    

    CRC8 byte, normal

    var
      CrcTable              : Array[0..255] of Cardinal; 
    
    function GenerateTableCrc8(Poly:Cardinal):Cardinal;
    var
      i                     : Cardinal;
    begin
    for i:=0 to 255 do CrcTable[i]:=Crc8(chr(i),Poly,0);
    end;
    
    function Crc8Byte(Buffer:String;Initial:Cardinal):Cardinal;
    var
      i                     : Cardinal;
    begin
    Result:=Initial;
    for i:=1 to Length(Buffer) do begin
      Result:=(Result shl 8) xor CrcTable[(ord(Buffer[i]) xor (Result)) and $ff];
      end;
    Result:=Result and $ff;
    end;
    

    CRC8 byte, inverted/reversed/reflected

    var
      CrcTable              : Array[0..255] of Cardinal; 
    
    function GenerateTableCrc8Reverse(Poly:Cardinal):Cardinal;
    var
      i                     : Cardinal;
    begin
    for i:=0 to 255 do CrcTable[i]:=Crc8Reverse(chr(i),Poly,0);
    end;
    
    function Crc8ByteReverse(Buffer:String;Initial:Cardinal):Cardinal;
    var
      i                     : Cardinal;
    begin
    Result:=Initial;
    for i:=1 to Length(Buffer) do begin
      Result:=(Result shr 8) xor CrcTable[(ord(Buffer[i]) xor Result) and $ff];
      end;
    end;
    

    CRC16

    The following polynomial are used:
    NormalInverted/reversed/reflected
    $8005$A001Std.
    $1021$8408CCITT, X24
    $4003$C002
    $0811$8810

    CRC16 bit, normal

    function crc16(Buffer:String;Polynom,Initial:Cardinal):Cardinal;
    var
      i,j                   : Integer;
    begin
    Result:=Initial;
    for i:=1 to Length(Buffer) do begin
      Result:=Result xor (ord(buffer[i]) shl 8);
      for j:=0 to 7 do begin
        if (Result and $8000)<>0 then Result:=(Result shl 1) xor Polynom
        else Result:=Result shl 1;
        end;
      end;
    Result:=Result and $ffff;
    end;
    

    CRC16 bit, inverted/reversed/reflected

    Remember to use corresponding polynomial values.
    function crc16reverse(Buffer:String;Polynom,Initial:Cardinal):Cardinal;
    var
      i,j                   : Integer;
    begin
    Result:=Initial;
    for i:=1 to Length(Buffer) do begin
      Result:=Result xor ord(buffer[i]);
      for j:=0 to 7 do begin
        if (Result and $0001)<>0 then Result:=(Result shr 1) xor Polynom
        else Result:=Result shr 1;
        end;
      end;
    end;
    

    CRC16 byte, normal

    var
      CrcTable              : Array[0..255] of Cardinal; 
    
    function GenerateTableCrc16(Poly:Cardinal):Cardinal;
    var
      i                     : Cardinal;
    begin
    for i:=0 to 255 do CrcTable[i]:=Crc16(chr(i),Poly,0);
    end;
    
    function Crc16Byte(Buffer:String;Initial:Cardinal):Cardinal;
    var
      i                     : Cardinal;
    begin
    Result:=Initial;
    for i:=1 to Length(Buffer) do begin
      Result:=(Result shl 8) xor CrcTable[(ord(Buffer[i]) xor (Result shr 8)) and $ff];
      end;
    Result:=Result and $ffff;
    end;
    

    CRC16 byte, inverted/reversed/reflected

    var
      CrcTable              : Array[0..255] of Cardinal; 
    
    function GenerateTableCrc16Reverse(Poly:Cardinal):Cardinal;
    var
      i                     : Cardinal;
    begin
    for i:=0 to 255 do CrcTable[i]:=Crc16Reverse(chr(i),Poly,0);
    end;
    
    function Crc16ByteReverse(Buffer:String;Initial:Cardinal):Cardinal;
    var
      i                     : Cardinal;
    begin
    Result:=Initial;
    for i:=1 to Length(Buffer) do begin
      Result:=(Result shr 8) xor CrcTable[(ord(Buffer[i]) xor Result) and $ff];
      end;
    end;
    

    CRC32

    The following polynomial are used:
    NormalInverted/reversed/reflected
    $04C11DB7$EDB88320Std.

    CRC32 bit, normal

    function crc32(Buffer:String;Polynom,Initial:Cardinal):Cardinal;
    var
      i,j                   : Integer;
    begin
    Result:=Initial;
    for i:=1 to Length(Buffer) do begin
      Result:=Result xor (ord(buffer[i]) shl 24);
      for j:=0 to 7 do begin
        if (Result and $80000000)<>0 then Result:=(Result shl 1) xor Polynom
        else Result:=Result shl 1;
        end;
      end;
    end;
    

    CRC32 bit, inverted/reversed/reflected

    Remember to use corresponding polynomial values.
    function crc32reverse(Buffer:String;Polynom,Initial:Cardinal):Cardinal;
    var
      i,j                   : Integer;
    begin
    Result:=Initial;
    for i:=1 to Length(Buffer) do begin
      Result:=Result xor ord(buffer[i]);
      for j:=0 to 7 do begin
        if (Result and $00000001)<>0 then Result:=(Result shr 1) xor Polynom
        else Result:=Result shr 1;
        end;
      end;
    end;
    

    CRC32 byte, normal

    var
      CrcTable              : Array[0..255] of Cardinal; 
    
    function GenerateTableCrc32(Poly:Cardinal):Cardinal;
    var
      i                     : Cardinal;
    begin
    for i:=0 to 255 do CrcTable[i]:=Crc32(chr(i),Poly,0);
    end;
    
    function Crc32Byte(Buffer:String;Initial:Cardinal):Cardinal;
    var
      i                     : Cardinal;
    begin
    Result:=Initial;
    for i:=1 to Length(Buffer) do begin
      Result:=(Result shl 8) xor CrcTable[(ord(Buffer[i]) xor (Result shr 24)) and $ff];
      end;
    Result:=Result;
    end;
    

    CRC32 byte, inverted/reversed/reflected

    var
      CrcTable              : Array[0..255] of Cardinal; 
    
    function GenerateTableCrc32Reverse(Poly:Cardinal):Cardinal;
    var
      i                     : Cardinal;
    begin
    for i:=0 to 255 do CrcTable[i]:=Crc32Reverse(chr(i),Poly,0);
    end;
    
    function Crc32ByteReverse(Buffer:String;Initial:Cardinal):Cardinal;
    var
      i                     : Cardinal;
    begin
    Result:=Initial;
    for i:=1 to Length(Buffer) do begin
      Result:=(Result shr 8) xor CrcTable[(ord(Buffer[i]) xor Result) and $ff];
      end;
    end;
    

    Notes


    Other pages