5 votos

¿Cuál es la forma correcta de este algoritmo CRC

Estamos trabajando en la comunicación entre el AVR y un Crous PTZ.

Hemos encontrado el protocolo y ahora podemos encenderla y así.

Tenemos problema con su CRC. Este es Crous protocolo doc (lo Tengo aquí), al final de la misma, el CRC algoritmo se describe (ver imagen de abajo), pero parece que está mal porque el contador parámetro nunca va a ser 8 pero se comprueba para ver si es de 8 o no.

enter image description here

Nuestro codificador ha escribí el siguiente código para el algoritmo , pero regresó el CRC no es el mismo que el CRC devuelto por Crous dispositivo.

#include <stdint.h>

unsigned int crc_chk(unsigned char dta, unsigned char length) 
{ 
  int16_t j;
  uint16_t a,b,c; 
  uint16_t reg_crc=0x0000; 
  for( c = 0; c < length; c++ ) 
  { 
    a = reg_crc / 256;
    a ^= test_crc[dta];
    dta++; 
    a *= 256;
    b = reg_crc&0xff;
    reg_crc = a | b;
    for( j = 0; j < 8; j++ ) 
    { 
      if ( reg_crc & 0x8000 ) 
        reg_crc = ( reg_crc * 2 ) ^ 0X8005; /* LSB(b0)=1 */ 
      else 
        reg_crc = reg_crc * 2;
    } 
  } 
  return reg_crc; // the value that sent back to the CRC register finally 
}

Él encontró la verdadera CRC en el dispositivo responde, por ejemplo , En este dispositivo responder

01 BF 15 0F 94 95 96 97 9F 9E A2 A0 98 99 72 6B 6A 88 89 64 62 63 65 66 03 2D AC

y según la página 45 del protocolo de Doc, el CRC de

0F 94 95 96 97 9F 9E A2 A0 98 99 72 6B 6A 88 89 64 62 63 65 66

debe ser 2DAC, 03 muestra final de los datos, y el 15 es el tamaño de los datos que, cuando se calcula que en decimal, serán 21 que ver, tenemos 21 bytes.

¿Cuál es la forma correcta de este algoritmo?

18voto

Metaxis Puntos 191

No hay nada de malo con el CRC de computación que son simplemente el cálculo del CRC para lo malo.

Los datos que desea enviar es:

0F 94 95 96 97 9F 9E A2 A0 98 99 72 6B 6A 88 89 64 62 63 65 66

Una vez se enmarca de forma adecuada para su transmisión a Crous PTZ, el real de bytes que están enviando es

01 BF 15 0F 94 95 96 97 9F 9E A2 A0 98 99 72 6B 6A 88 89 64 62 63 65 66 03

El CRC 2DAC es para la trama como un todo, no sólo los datos en ella. El código siguiente es esencialmente versión sin modificar del código que calcula el CRC para el marco, y se puede ver que se deriva el valor correcto.

#include <stdio.h>
#include <stdint.h>

int main (void) { 
    unsigned char test_crc[] = {
        0x01, 0xBF, 0x15, 0x0F, 0x94, 0x95, 0x96, 0x97, 0x9F, 0x9E, 0xA2, 0xA0, 0x98, 0x99, 0x72, 0x6B, 0x6A, 0x88, 0x89, 0x64, 0x62, 0x63, 0x65, 0x66, 0x03
    };

    int length = sizeof test_crc / sizeof test_crc[0];
    unsigned char dta = 0;
    int16_t j;
    uint16_t a,b,c; 
    uint16_t reg_crc=0x0000; 
    for( c = 0; c < length; c++ ) 
    { 
        printf("0x%02x%c", test_crc[dta], (dta+1)%5?' ':'\n');

        a = reg_crc / 256;
        a ^= test_crc[dta];
        dta++; 
        a *= 256;
        b = reg_crc&0xff;
        reg_crc = a | b;
        for( j = 0; j < 8; j++ ) 
        { 
            if ( reg_crc & 0x8000 ) 
                reg_crc = ( reg_crc * 2 ) ^ 0X8005; /* LSB(b0)=1 */ 
            else 
            reg_crc = reg_crc * 2;
        } 
    } 
    printf("\n");
    printf("CRC: 0x%04X\n", reg_crc);
    return 0;
}

Cuando se ejecuta:

$ make crc16-orig && ./crc16-orig
cc     crc16-orig.c   -o crc16-orig
0x01 0xbf 0x15 0x0f 0x94
0x95 0x96 0x97 0x9f 0x9e
0xa2 0xa0 0x98 0x99 0x72
0x6b 0x6a 0x88 0x89 0x64
0x62 0x63 0x65 0x66 0x03

CRC: 0xAC2D

Mientras que el código es funcionalmente correcto, se podría hacer con algunas mejoras. @vicatcu versión es mucho más agradable.

4voto

JW. Puntos 145

A simple vista, parece que el "contador = 8?" decisión de bloquear probablemente debería tener un "NO" ruta de acceso que retroalimenta a, probablemente, "el bit 15 CRC = 1?" la decisión del bloque de entrada. Y la salida de la "contador = 8?" decisión bloque debe ser marcado "SÍ"...

Como para la implementación, estoy teniendo algunos problemas para hacer sentido de ella. ¿Qué es test_crc y donde se define? No dta ser un puntero en la función de la firma? He hecho algunos cambios en el código de post para mejorar la legibilidad.

Yo fielmente implementado una función que se basa en el diagrama de bloques y mi suposición y corrió en IDEOne y obtener el resultado creo que usted espera... aquí está mi código.

#include <stdio.h>
#include <stdint.h>

unsigned int crc16(uint8_t * data, uint8_t length) 
{ 
  uint16_t CRC = 0;
  uint16_t A = 0, B = 0;
  uint8_t index = 0, Counter = 0; 

  for( index = 0; index < length; index++ )
  {
    uint8_t byte = data[index];

    A = CRC / 256;
    A = A ^ byte;
    A = A * 256;

    B = CRC & 0xFF;
    CRC = A | B;

    for( Counter = 0; Counter < 8; Counter++ ){
      if( CRC & 0x8000 )
      {
        CRC = CRC * 2;
        CRC = CRC ^ 0x8005;
      }
      else
      {
        CRC = CRC * 2;
      }
    }
  }
  return CRC;
}

int main(int argc, char *argv[]){
  uint8_t data[] = { 0x01, 0xBF, 0x15, 0x0F, 0x94, 0x95, 0x96, 0x97, 0x9F, 0x9E, 0xA2, 0xA0, 0x98, 0x99, 0x72, 0x6B, 0x6A, 0x88, 0x89, 0x64, 0x62, 0x63, 0x65, 0x66, 0x03 };
  uint8_t length = sizeof(data);
  uint16_t crc = 0;

  printf("Length = %d\n", length);
  crc = crc16(data, length);
  printf("CRC = %04x", crc);

  return 0;

}

Se emite:

Length = 25
CRC = ac2d

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X