CRC calculations
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
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.
The following polynomial are used:
| Normal | Inverted/reversed/reflected |
| $07 | $e0 |
| $31 | $8C |
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;
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;
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;
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;
The following polynomial are used:
| Normal | Inverted/reversed/reflected |
| $8005 | $A001 | Std. |
| $1021 | $8408 | CCITT, X24 |
| $4003 | $C002 | |
| $0811 | $8810 | |
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;
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;
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;
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;
The following polynomial are used:
| Normal | Inverted/reversed/reflected |
| $04C11DB7 | $EDB88320 | Std. |
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;
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;
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;
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;
- Cardinal: 32 bit unsigned integer, but in crc8 and crc16 a shorter variable can be used
- and: Same as & in C
- xor: Same as ^ in C
- shl: Same as << in C
- shr: Same as >> in C
- <>: Same as != in C
- String: A string of byte size characters with dynamic length
- ord: Type cast the value of a character to a integer
- chr: Type cast the value of a integer to a character and in this case to a string with the length of 1
- Remark: The code for all reverse algorithms are the same as long as calculation are done in 32 bits
Other pages
- MPU Support list where MiscEl can help when working with microprocessors