• Viernes 3 de Mayo de 2024, 13:46

Autor Tema:  crc16 ccitt polinomio 1021  (Leído 3590 veces)

blasata

  • Miembro activo
  • **
  • Mensajes: 32
    • Ver Perfil
crc16 ccitt polinomio 1021
« en: Domingo 7 de Noviembre de 2010, 02:59 »
0
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
  1.  
  2. long CRC16(char value, long poly, long init_value, long exit_value)
  3. {
  4.     long re, i;
  5.     res=value;
  6.  
  7.     res^=init_value;
  8.  
  9.     for(i=0; i<8; i++)  // a cada byte hacer
  10.     {
  11.         if(res & 1)
  12.            {
  13.             res >>= 1;
  14.             res ^= poly;      // 1021
  15.            }
  16.         else
  17.            {
  18.             res >>= 1;
  19.            }
  20.     }
  21.    res ^= exit_value;
  22.    return res;
  23. }
  24. int _tmain(int argc, _TCHAR* argv[])
  25. {
  26.     char datos[]="123456789";
  27.     int i;
  28.     long inival;
  29.     inival=0xFFFF;
  30.  
  31.     for(i=0; i<strlen(datos); i++)
  32.       {
  33.          printf("INIVAL VALE: %Xn",inival);
  34.        inival = CRC16(datos[i],0x1021,inival,0x0000);
  35.       }
  36.     inival = inival ^ 0xFFFF;
  37.     printf("El CRC de la cadena: %s es: %4Xn", datos, inival);
  38.     getchar();
  39.     return 0;
  40. }
  41.  
  42.  

muchas gracias

blasata

  • Miembro activo
  • **
  • Mensajes: 32
    • Ver Perfil
Re: crc16 ccitt polinomio 1021
« Respuesta #1 en: Lunes 8 de Noviembre de 2010, 00:47 »
0
bueno ya tengo una función que lo hace bien:

Código: C
  1. static int calcByte(int crc, int b)
  2. {
  3.     crc = crc ^ (int)b << 8;
  4.     for (int i = 0; i < 8; i++)
  5.         {
  6.             if ((crc & 0x8000) == 0x8000)
  7.                 crc = crc << 1 ^ 0x1021;
  8.             else
  9.                 crc = crc << 1;
  10.         }
  11.     return crc & 0xffff;
  12. }
  13.  
  14.  

Y el resto algo así
Código: C
  1. char datos[30]="000903000200000003";
  2.     int i, crc;
  3.     crc=0xFFFF;
  4.  
  5.     for(i=0;i<strlen(datos);i++)    
  6.          crc = calcByte(crc, datos[i]);
  7.    
  8.    
  9.     printf("El CRC de la cadena: %s es: %4X, y el C1 es: %4Xn",datos,crc,~crc);
  10.  

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

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: crc16 ccitt polinomio 1021
« Respuesta #2 en: Lunes 8 de Noviembre de 2010, 11:48 »
0
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
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

  • Miembro activo
  • **
  • Mensajes: 32
    • Ver Perfil
Re: crc16 ccitt polinomio 1021
« Respuesta #3 en: Martes 9 de Noviembre de 2010, 11:07 »
0
La solución que he encontrado:

Código: C
  1. #define                 P_CCITT     0x1021
  2.  
  3.  
  4. static int              crc_tabccitt_init       = FALSE;
  5. static unsigned short   crc_tabccitt[256];
  6.  
  7. static void init_crcccitt_tab( void )
  8.  { 
  9.     int i, j;
  10.     unsigned short crc, c;
  11.     for (i=0; i<256; i++)
  12.         {
  13.         crc = 0;
  14.         c   = ((unsigned short) i) << 8;
  15.         for (j=0; j<8; j++)
  16.                {
  17.                  if ( (crc ^ c) & 0x8000 ) crc = ( crc << 1 ) ^ P_CCITT;
  18.                  else                      crc =   crc << 1;
  19.                  c = c << 1;
  20.                }
  21.          crc_tabccitt[i] = crc;
  22.     }
  23.     crc_tabccitt_init = TRUE;
  24. }  /* init_crcccitt_tab */
  25.  
  26. unsigned short update_crc_ccitt( unsigned short crc, char c ) {
  27.  
  28.     unsigned short tmp, short_c;
  29.     short_c  = 0x00ff & (unsigned short) c;
  30.     if ( ! crc_tabccitt_init )
  31.         init_crcccitt_tab();
  32.     tmp = (crc >> 8) ^ short_c;
  33.     crc = (crc << 8) ^ crc_tabccitt[tmp];
  34.     return crc;
  35. }  
  36. char input_string[20]="000311r";
  37.     char *ptr, *dest, hex_val, prev_byte;
  38.     unsigned short crc_ccitt_ffff;
  39.  
  40.     ptr  = input_string;
  41.     dest = input_string;
  42.     while( *ptr  &&  *ptr != 'r'  &&  *ptr != 'n' )
  43.        {
  44.             if ( *ptr >= '0'  &&  *ptr <= '9' ) *dest++ = (char) ( (*ptr) - '0'      );
  45.             if ( *ptr >= 'A'  &&  *ptr <= 'F' ) *dest++ = (char) ( (*ptr) - 'A' + 10 );
  46.             if ( *ptr >= 'a'  &&  *ptr <= 'f' ) *dest++ = (char) ( (*ptr) - 'a' + 10 );
  47.             ptr++;
  48.        }
  49.      * dest    = 'x80';
  50.      *(dest+1) = 'x80';
  51.         crc_ccitt_ffff = 0xffff;
  52.         prev_byte = 0;
  53.         ptr       = input_string;
  54.  
  55.         while ( *ptr != 'x80' )
  56.             {
  57.                 hex_val  = (char) ( ( * ptr     &  'x0f' ) << 4 );
  58.                 hex_val |= (char) ( ( *(ptr+1)  &  'x0f' )      );              
  59.                 crc_ccitt_ffff = update_crc_ccitt(  crc_ccitt_ffff, hex_val            );
  60.                 prev_byte = hex_val;
  61.                 ptr      += 2;
  62.              }
  63.  
  64.            //input_string[0] = 0;
  65.  printf( "CRC-CCITT (0xffff) = 0x%04Xn", crc_ccitt_ffff);
  66.    
  67.     getchar();
  68.     return 0;
  69.  

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: