Saltar al contenido

Función para calcular una suma de comprobación CRC16

No olvides que en las ciencias un error suele tener diferentes resoluciones, de igual modo nosotros te compartimos lo mejor y más eficiente.

Solución:

Hay varios detalles con los que debe ‘coincidir’ para una implementación de CRC en particular; incluso usando el mismo polinomio, puede haber resultados diferentes debido a diferencias menores en cómo se manejan los bits de datos, usando un valor inicial particular para el CRC (a veces es cero, a veces 0xffff), y/o invertir los bits del CRC. Por ejemplo, a veces una implementación funcionará desde los bits de orden inferior de los bytes de datos hacia arriba, mientras que a veces funcionará desde los bits de orden superior hacia abajo (como lo hace actualmente la suya).

Además, debe ‘expulsar’ los últimos bits del CRC después de haber ejecutado todos los bits de datos.

Tenga en cuenta que los algoritmos CRC se diseñaron para implementarse en hardware, por lo que parte de la forma en que se maneja el orden de bits puede no tener mucho sentido desde el punto de vista del software.

Si desea hacer coincidir el CRC16 con el polinomio 0x8005 como se muestra en la página de la calculadora CRC de lammertbies.nl, debe realizar los siguientes cambios en su función CRC:

  • a) ejecutar los bits de datos a través del bucle CRC comenzando desde el bit menos significativo en lugar del bit más significativo
  • b) extraiga los últimos 16 bits del CRC del registro CRC una vez que haya terminado con los datos de entrada
  • c) invertir los bits CRC (supongo que este bit es un remanente de implementaciones de hardware)

Entonces, su función podría verse así:

#define CRC16 0x8005

uint16_t gen_crc16(const uint8_t *data, uint16_t size)

    uint16_t out = 0;
    int bits_read = 0, bit_flag;

    /* Sanity check: */
    if(data == NULL)
        return 0;

    while(size > 0)
    = (*data >> bits_read) & 1; // item a) work from the least significant bits

        /* Increment bit counter: */
        bits_read++;
        if(bits_read > 7)
        
            bits_read = 0;
            data++;
            size--;
        

        /* Cycle check: */
        if(bit_flag)
            out ^= CRC16;

    

    // item b) "push out" the last 16 bits
    int i;
    for (i = 0; i < 16; ++i) 
        bit_flag = out >> 15;
        out <<= 1;
        if(bit_flag)
            out ^= CRC16;
    

    // item c) reverse the bits
    uint16_t crc = 0;
    i = 0x8000;
    int j = 0x0001;
    for (; i != 0; i >>=1, j <<= 1) 
        if (i & out) crc 

    return crc;

Esa función devuelve 0xbb3d para mí cuando paso "123456789".

Aquí sigue un código de trabajo para calcular crc16 CCITT. Lo probé y los resultados coincidieron con los proporcionados por http://www.lammertbies.nl/comm/info/crc-calculation.html.

unsigned short crc16(const unsigned char* data_p, unsigned char length)
    unsigned char x;
    unsigned short crc = 0xFFFF;

    while (length--)
        x = crc >> 8 ^ *data_p++;
        x ^= x>>4;
        crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x <<5)) ^ ((unsigned short)x);
    
    return crc;

Hay varias variedades diferentes de CRC-16. Ver página wiki.

Cada uno de ellos devolverá resultados diferentes de la misma entrada.

Por lo tanto, debe seleccionar cuidadosamente el correcto para su programa.

Si haces scroll puedes encontrar las reseñas de otros gestores de proyectos, tú incluso puedes mostrar el tuyo si dominas el tema.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *