[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