Programación General > C/C++

 crc16 ccitt polinomio 1021

(1/1)

blasata:
Hola a todos,
por favor alguien puede decirme que está mal en el siguiente código? me devuelve para la cadena "123456789" un valor de CRC de: E245. Sin embargo debería ser 29B1, según esta web: http://zorc.breitbandkatze.de/crc.html
Se trata de CRC16 CCITT, polinomio 0x1021, valor inicial 0xffff y final 0.
 :hitcomp:


--- Código: C --- long CRC16(char value, long poly, long init_value, long exit_value){    long re, i;    res=value;     res^=init_value;     for(i=0; i<8; i++)  // a cada byte hacer    {        if(res & 1)           {            res >>= 1;            res ^= poly;      // 1021           }        else           {            res >>= 1;           }    }   res ^= exit_value;   return res;}int _tmain(int argc, _TCHAR* argv[]){    char datos[]="123456789";    int i;    long inival;    inival=0xFFFF;     for(i=0; i<strlen(datos); i++)      {         printf("INIVAL VALE: %Xn",inival);       inival = CRC16(datos[i],0x1021,inival,0x0000);      }    inival = inival ^ 0xFFFF;    printf("El CRC de la cadena: %s es: %4Xn", datos, inival);    getchar();    return 0;}  
muchas gracias

blasata:
bueno ya tengo una función que lo hace bien:


--- Código: C ---static int calcByte(int crc, int b){    crc = crc ^ (int)b << 8;    for (int i = 0; i < 8; i++)        {            if ((crc & 0x8000) == 0x8000)                crc = crc << 1 ^ 0x1021;            else                crc = crc << 1;        }    return crc & 0xffff;}  
Y el resto algo así

--- Código: C ---char datos[30]="000903000200000003";    int i, crc;    crc=0xFFFF;      for(i=0;i<strlen(datos);i++)              crc = calcByte(crc, datos[i]);            printf("El CRC de la cadena: %s es: %4X, y el C1 es: %4Xn",datos,crc,~crc); 
Pero ahora lo que quiero es que me trate la cadena datos como Hex, porque tal como está los trata como ASCII. Esto lo podeis ver en la web http://www.lammertbies.nl/comm/info/crc-calculation.html
Alli podeis seleccionar la cadena como ASCII o como Hex, y como ASCII mi porgrama y la web coinciden, pero necesito el resultado que da con la opción Hex, ¿alguna idea?

Para más datos la definición de CRC que debo usar es esta:

CRC-CCITT
16 bits
Poly 0x1021
Forward
Preset FFFF
Residuo 1D0F

Y lo que trato de conseguir es obtener para 00 09 03 00 02 00 00 00 03 un CRC de 12E6 (que es el Complento a 1 de ED19, resultado que da la web con la opción Hex marcada)

gracias

m0skit0:

--- Cita de: "blasata" ---Pero ahora lo que quiero es que me trate la cadena datos como Hex, porque tal como está los trata como ASCII
--- Fin de la cita ---
Necesitas validar y convertir la cadena de caracteres al valor hexadecimal que representa. No hay ninguna forma sencilla de hacerlo, así que tienes que crearte una función que lo haga.

EDITO: también puedes echarle un vistazo a la función strtol().

blasata:
La solución que he encontrado:


--- Código: C ---#define                 P_CCITT     0x1021  static int              crc_tabccitt_init       = FALSE;static unsigned short   crc_tabccitt[256]; static void init_crcccitt_tab( void ) {     int i, j;    unsigned short crc, c;    for (i=0; i<256; i++)         {        crc = 0;        c   = ((unsigned short) i) << 8;        for (j=0; j<8; j++)                {                 if ( (crc ^ c) & 0x8000 ) crc = ( crc << 1 ) ^ P_CCITT;                 else                      crc =   crc << 1;                 c = c << 1;               }         crc_tabccitt[i] = crc;    }    crc_tabccitt_init = TRUE;}  /* init_crcccitt_tab */ unsigned short update_crc_ccitt( unsigned short crc, char c ) {     unsigned short tmp, short_c;    short_c  = 0x00ff & (unsigned short) c;    if ( ! crc_tabccitt_init )         init_crcccitt_tab();    tmp = (crc >> 8) ^ short_c;    crc = (crc << 8) ^ crc_tabccitt[tmp];    return crc;}  char input_string[20]="000311r";    char *ptr, *dest, hex_val, prev_byte;    unsigned short crc_ccitt_ffff;     ptr  = input_string;    dest = input_string;    while( *ptr  &&  *ptr != 'r'  &&  *ptr != 'n' )        {            if ( *ptr >= '0'  &&  *ptr <= '9' ) *dest++ = (char) ( (*ptr) - '0'      );            if ( *ptr >= 'A'  &&  *ptr <= 'F' ) *dest++ = (char) ( (*ptr) - 'A' + 10 );            if ( *ptr >= 'a'  &&  *ptr <= 'f' ) *dest++ = (char) ( (*ptr) - 'a' + 10 );            ptr++;       }     * dest    = 'x80';     *(dest+1) = 'x80';        crc_ccitt_ffff = 0xffff;        prev_byte = 0;        ptr       = input_string;         while ( *ptr != 'x80' )             {                hex_val  = (char) ( ( * ptr     &  'x0f' ) << 4 );                hex_val |= (char) ( ( *(ptr+1)  &  'x0f' )      );                              crc_ccitt_ffff = update_crc_ccitt(  crc_ccitt_ffff, hex_val            );                prev_byte = hex_val;                ptr      += 2;             }            //input_string[0] = 0; printf( "CRC-CCITT (0xffff) = 0x%04Xn", crc_ccitt_ffff);        getchar();    return 0; 
Para la cadena 000311 da CRC de 9BDF, luego lo pongo en Complemento a 1 y el cacharro ya me responde a lo comandos que le mando por fin!
saludos :good:

Navegación

[0] Índice de Mensajes

Ir a la versión completa