[gull] crc récalcitrant
Frédéric Benninger
benninger at sunrise.ch
Fri Oct 14 21:45:08 CEST 2011
Bonjour,
Je me prend la tête sur le calcul d'un CRC en Perl.
J' écris un script permettant de dialoguer avec une station météo
utilisant le protocole UMB.
Le protocole utilise une somme de contrôle sur 16 bits pour valider les trames.
La doc dit que c'est un CRC-CCITT et donne un exemple en C.
En Perl avec le script suivent j'obtiens 0xf134 et ce n'est pas un
résultat valide pour la station météo. :-(
#!/usr/bin/perl -w
use strict;
use Digest::CRC qw(crcccitt);
my $ctx = Digest::CRC->new(type=>"crcccitt");
$ctx->add('01234567');
print $ctx->hexdigest . "\n";
Par contre l'exemple en C ci-dessous retourne : 0xf843 ce qui devrait
en théorie être valide car c'est dans la doc officielle du protocole
UMB.
Pouvez-vous me mettre sur une piste pour comprendre ce qui cloche?
Salutations
#include <stdio.h>
#include <string.h>
/*************************************************************************
Function:
16 bit CRC-CCITT calculation
--------------------------------------------------------------------------
Call:
calc_crc(unsigned short crc_buff, unsigned char input)
--------------------------------------------------------------------------
Response:
Newly calculated 16 bit CRC checksum
--------------------------------------------------------------------------
Description: Calculates the checksum for 'input' in accordance with the
CRC polynomial x^16 + x^12 + x^5 + 1.
'crc_buff' is the previously calculated checksum. This must
be set to 0xFFFF at the beginning of a test sequence.
*************************************************************************/
unsigned short calc_crc(unsigned short crc_buff, unsigned char input)
{
unsigned char i;
unsigned short x16; // we’ll use this to hold the XOR mask
for (i=0; i<8; i++)
{
// XOR current D0 and next input bit to determine x16 value
if( (crc_buff & 0x0001) ^ (input & 0x01) )
x16 = 0x8408;
else
x16 = 0x0000;
// shift crc buffer
crc_buff = crc_buff >> 1;
// XOR in the x16 value
crc_buff ^= x16;
// shift input for next iteration
input = input >> 1;
}
return(crc_buff);
}
// ******************* MAIN ************************************
void main(void)
{
// example: CRC for 8 Bytes
unsigned char values[8] =
{0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37};
// initialise startvalue FFFFh
unsigned short crc = 0xFFFF;
// calculation
for(int n = 0; n < 8; n++)
{
crc = calc_crc(crc, values[n]);
}
// output
printf("\ndata: 30h, 31h, 32h, 33h, 34h, 35h, 36h, 37h");
printf("\nCRC:
%04Xh\n", crc);
}
More information about the gull
mailing list