Calcul CRC-CCITT kermit

Publié le 13 avril 2010 par Geeku

Suite à un développement compliqué sur les calculs du CRC-CCITT (kermit) pour vérifier le CRC des communications port série, je vous fourni le code Delphi du calcul.

Le CRC-CCITT (kermit) est calculé sur un polynôme de type x^16+x^12+x^5

La chaine en ASCII de « 1234567803″ donnera le CRC  en hexa=E8CD  et en binaire 59597

La chaine en hexa de « 1234567803″ donnera le CRC  en hexa=73C5  et en binaire 29637

Code source

function CalcCRC16Kermit_ccitt(Chn: string): Word;
var
I: Integer;
a, d: Word;
crc,low_byte,high_byte: Word;
hex_val: Integer;

procedure CalcCRC16Kermit(car: Char);
begin
d:= crc;
d:= d xor    ( ord(car) and $ff ); // 1
a:= ( d xor    ( d shl    4 ) ) and $ff; // 2
d:= ( d shr 8 ) xor ( a shl 8 ) xor ( a shl     3 ) xor ( a shr 4 ); // 3
d:= d and $ffff; // only for portability
crc:= d;
end;

begin
Result:= 0;
Chn:= Chn + ‘ZZ’; //les zz sont utiles pour reperer la fin de traitement
crc:= 0;

I:=1;
while Chn[i] <> ‘Z’ do
begin
hex_val:=  ( ( ord(Chn[i])     and  $0f ) shl 4 );
hex_val:= hex_val or ( ( ord(Chn[i+1])  and  $0f )      );
CalcCRC16Kermit(Chr(hex_val));

I:= I + 2;
end;

low_byte   := (crc and $ff00) shr 8;
high_byte  := (crc and $00ff) shl 8;
Result:= low_byte or high_byte;
end;

function CalcCRC16Kermit_ccitt2(Chn: string): Word;
var
I: Integer;
a, d: Word;
crc,low_byte,high_byte: Word;
hex_val: Integer;

procedure CalcCRC16Kermit(car: Char);
begin
d:= crc;
d:= d xor    ( ord(car) and $ff ); // 1
a:= ( d xor    ( d shl    4 ) ) and $ff; // 2
d:= ( d shr 8 ) xor ( a shl 8 ) xor ( a shl     3 ) xor ( a shr 4 ); // 3
d:= d and $ffff; // only for portability
crc:= d;
end;

begin
Result:= 0;
Chn:= Chn + ‘ZZ’; //les zz sont utiles pour reperer la fin de traitement
crc:= 0;

I:=1;
while Chn[i] <> ‘Z’ do
begin
hex_val:=  ( ( ord(Chn[i])     and  $0f ) shl 4 );
hex_val:= hex_val or ( ( ord(Chn[i+1])  and  $0f )      );
CalcCRC16Kermit(Chr(hex_val));

I:= I + 2;
end;

low_byte   := (crc and $ff00) shr 8;
high_byte  := (crc and $00ff) shl 8;
Result:= low_byte or high_byte;
end;