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
Ir a la versión completa