TODOPIC
Bienvenido(a), Visitante. Por favor, ingresa o regístrate.
¿Perdiste tu email de activación?
21 de Agosto de 2014, 09:05:01

Ingresar con nombre de usuario, contraseña y duración de la sesión
Buscar:     Búsqueda Avanzada
347431 Mensajes en 38985 Temas por 40581 Usuarios
Último usuario: Fuentes84
* Inicio Ayuda Buscar Calendario Ingresar Registrarse
Buscar en TodoPIC
+  TODOPIC
|-+  Microcontroladores PIC
| |-+  Todo en microcontroladores PIC (Moderadores: marmatar, maunix, MGLSOFT, Modulay, pocher, Sasián, Suky)
| | |-+  Necesito ayuda para calcular CRC-16
0 Usuarios y 1 Visitante están viendo este tema. « anterior próximo »
Páginas: [1] Marcar como favorito Imprimir
Autor Tema: Necesito ayuda para calcular CRC-16  (Leído 11572 veces)
Automata78
PIC12
**
Desconectado Desconectado

Mensajes: 59


« : 30 de Junio de 2008, 16:02:12 »

   Hola a todos !!...antes que nada quería comentar que estuve leyendo sobre este tema en el foro, pero no me ha quedado claro la idea del codigo que se puede ver en http://www.todopic.com.ar/foros/index.php?topic=17709.0 , le codigo es el siguiente :
2.5 CRC16 Calculation Algorithm
Polynomial: x16 + x12 + x5 + 1 Þ CRC_POLYNOM = 0x8408;
Start Value: 0xFFFF Þ CRC_PRESET = 0xFFFF;
C-Example:
unsigned internal CRC = CRC_PRESET;
for (i = 0; i < cnt; i++) /* cnt = number of protocol bytes without CRC */
{
crc ^= DATA;
for (j = 0; j < 8; j++)
{
if (crc & 0x0001)
crc = (crc >> 1) ^ CRC_POLYNOM;
else
crc = (crc >> 1);
}
}

No entiendo por ejemplo que lo que hace "crc ^=DATA;" es como que complementa DATA y lo guarda en crc, lo que quiero entender el la logica de este programa así lo puedo adaptar en assembler con un polinomio CRC-16 bits.

   Espero que no sea mucho pedir, desde ya muchas gracias por la ayuda.  saludos !!!!
En línea
MGLSOFT
Moderador Local
DsPIC33
*****
Desconectado Desconectado

Sexo: Masculino
Argentina Argentina

Mensajes: 7500


MGLSOFT


« Respuesta #1 : 30 de Junio de 2008, 16:24:26 »

Bueno, aqui te pongo una explicacion de como se obtiene el CRC para Modbus RTU.

Citar
Generación del CRC
El Chequeo de Redundancia Cíclica (CRC) está compuesto por dos bytes, conteniendo un valor binario de 16 Bits.

El valor del CRC es calculado por el transmisor y adjuntado al mensaje a transmitir. El receptor calcula un CRC con el mensaje recibido y lo compara con el valor del CRC recibido. Si los valores no coinciden se produce un error.

El CRC comienza cargando un registro de 16 bits con todos 1's. Luego comienza un proceso de aplicación de los sucesivos bytes del mensaje al contenido del registro. Solo los 8 bits de datos son usados para generar el CRC. Los bits de inicio, parada y paridad no se utilizan para el CRC.

Durante la generación del CRC, se ejecuta una operación lógica XOR entre cada byte y el contenido del registro. Luego el resultado es desplazado en la dirección del bit menos significativo (LSB), ingresando un 0 en la posición del bit más significativo (MSB). El bit extraído es examinado. Si es un 1 se ejecuta una XOR entre el contenido del registro y un valor fijo. Si el bit extraído es 0 no se ejecuta la XOR.

Este proceso se repite hasta ejecutarse ocho desplazamientos.

Después del último desplazamiento se ejecuta una XOR entre el próximo byte y el valor del registro de 16 bits, realizando el procedimiento de desplazamientos des cripta anteriormente.
El contenido final del registro, después de aplicarse todos los bytes del mensaje, es el valor del CRC.

El procedimiento para generar el CRC es:

1.   Cargar un registro de 16 bits con FFFFH (todos 1's). Este registro toma el nombre de registro CRC.

2.   Ejecutar una XOR entre el primer byte del mensaje y el byte menos significativo del registro CRC, dejando el resultado en el registro CRC.

3.   Desplazar el registro CRC un bit a la derecha (hacia el LSB), ingresando un 0 en el MSB. Extraer y examinar el LSB.

4.   Si el LSB fue 0 repetir el paso 3 (otro desplazamiento).   Si el MSB fue 1 realizar una XOR entre el registro CRC y el valor A001H (1010 0000 0000 0001 B).

5.   Repetir los pasos 3 y 4 hasta completar ocho desplazamientos, dando como procesado un byte.

6.   Repetir los pasos 2 a 5 para el próximo byte del mensaje. Continuar hasta que todos los bytes han sido procesados.

7.   El contenido final del registro CRC es el valor CRC. Cuando el CRC (dos bytes) es transmitido en el mensaje, el byte menos significativo debe ser transmitido primero, seguido del byte más significativo.
« Última modificación: 01 de Julio de 2008, 15:18:51 por MGLSOFT » En línea

Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.
Automata78
PIC12
**
Desconectado Desconectado

Mensajes: 59


« Respuesta #2 : 30 de Junio de 2008, 19:57:48 »

hola MGLSOFT !!!!!!!  ........... muchas gracias .... me parece excelente la explicacion, esta noche misma me voy a poner a programar la ruitna, y cuendo tenga el resultado te cuento !!!!
   Muchisimas gracias por tu aporte MGLSOFT !!!!  saludos !!!!
En línea
Automata78
PIC12
**
Desconectado Desconectado

Mensajes: 59


« Respuesta #3 : 01 de Julio de 2008, 11:27:52 »

hola MGLSOFT !!!

  Te cuento que hice un programilla en C y assembler, .... el resultado no es muy satisfactorio, ya que para valores de datos "1,2,3,4,5,6,7,8,9"

  me devuelve crc_H = 0xB1 y crc_L = 64 en vez de 0xB1 y 0x29 respectivamente...
  Aqui te cuelgo el código por si ves algo raro, lo unico que queria señalar es que yo roto el registro crc a la izquierda y no a la derecha y compruebo  el bit mas significativo, o sea bit 7 del crc_H ! ya que en los datos, el bit mas significativo se encuentra a la izquierda, te pido por favor si este razonamiento es el correcto o estoy cometiendo un error.

   Muchisimas gracias a vos y a cualquiera que quiera ayudar en esta consulta  !   saludossss !!!


#include "D:\Medidor_Agua\CRC_Prueba\CRC16.h"

#BYTE STATUS = 0X03


byte DATA[]={'1','2','3','4','5','6','7','8','9'};
byte i,j;

byte crc_H,crc_L;
byte cnt = 9;





void Ini_Port(void)
{
 set_tris_a(0);
 set_tris_b(0x0);
 output_a(0);
 output_b(0);
}

void Ini_Var(void)
{
 

}

void main()
{

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
//Setup_Oscillator parameter not selected from Intr Oscillotar Config tab

   // TODO: USER CODE!!
   
   Ini_Port();
   
   

crc_L = 0xff;
crc_H = 0xff;

for (i = 0; i < cnt; i++) // cnt = number of protocol bytes without CRC
    {
     crc_L ^= DATA;

     for (j = 0; j < 8; j++)
         {
          if ((crc_H & 0x80) == 0x80)
             {
              #asm
              bcf         STATUS,0     //borro carry
              rlf          crc_L,F
              rlf          crc_H,F
              movlw    0x10
              xorwf     crc_H,F
              movlw    0x21
              xorwf     crc_L,F
              #endasm
             }
          else{
              #asm
              bcf         STATUS,0     //borro carry
              rlf          crc_L,F
              rlf          crc_H,F
              #endasm
               }
         }
    }
   
   

}
« Última modificación: 01 de Julio de 2008, 11:31:14 por Automata78 » En línea
Automata78
PIC12
**
Desconectado Desconectado

Mensajes: 59


« Respuesta #4 : 09 de Julio de 2008, 10:36:45 »

Hola nuevamente..... les cuento que sigo intentandolo pero no tengo buenos resultados, y por lo que he leido, los pasos no son demasiados complicados. Se los explico con mis palabras lo que entiendo.
 
cargo variable CRC con 0xFFFF

luego:

P1 : desplazo una pocisión a la izquierda,

P2 :verifico si el bit mas significativo es igual a '1',   si es '1'  realizo una operacion XOR entre la variable CRC y 0x1021 y el resultado lo guardo en CRC.
, y si en la verificación anterior no fuera uno, no hago nada,

P3 : realizo los pasos P1 y P2 por los 16 bits !

Sobre lo que he leido en internet, lo que no entiendo es eso de cargar a la variable CRC con 0xFFFF en vez de comenzar en cero.
 y lo otro que tambien no entiendo es si debo agregarle a mi cadena de datos 2 bytes mas cargados con 'cero' antes de realizar la operacion para hallar el CRC-16.

 Espero que me puedan aclarar este problema, ya que le he dedicado mucho tiempo y sigo parada en el mismo lugar ! je je je
 muchas gracias a todos, nos estamos leyendo. saludos !
En línea
Javicho
Colaborador
PIC24F
*****
Desconectado Desconectado

Peru Peru

Mensajes: 570


« Respuesta #5 : 09 de Julio de 2008, 11:03:40 »

Hola:

Hace tiempo también tuve el dilema del CRC16 y por ahi encontré un código, aquí está zipeado, no lo llegué a probar porque solucioné el impase por otro método.

Espero te sirva.

Javicho
En línea
pctecnologia
PIC10
*
Desconectado Desconectado

Costa Rica Costa Rica

Mensajes: 1


« Respuesta #6 : 17 de Junio de 2011, 18:20:20 »

Buenas, tengo la siguiente especificación para aplicar el CRC16 a una cadena de texto, pero no me queda claro como hacerlo, por favor si alguiente puede ayudarmen:

VoiceCode Specification
A VoiceCode is a 4 digit number computed using the GTIN, Lot, and optional Date from a PTI Case Label representing a hash of this information. This computation is performed
as follows:

1) Compute  PlainText
a. PlainText is the 14 digit GTIN appended by the Lot Code and the Date (where present) in that order.
b. Do not include the application identifier, prefixes or parentheses
c. There are no spaces between the GTIN, Lot and Date fields.
d. Date if present is represented as YYMMDD with zero packing and no “/” characters
2) Compute ANSI CRC-­‐16 Hash of the PlainText ASCII bytes using the standard ANSI CRC-­‐16 hash with the polynomial of X16 + X15 + X2 + 1
3) Compute the VoiceCode by from the Hash by taking the 4 least significant digits in decimal form (Hash mod 10000).
4) Print the two least significant digits large, and the two most significant digits small Example:

GTIN = (01)10850510002011
Lot = (10)46587443HG234
PlainText=1085051000201146587443HG234
CRC-­‐16 Hash=26359
VoiceCode=6359
Large Digits = 59
Small Digits= 63
En línea
Suky
Moderador Local
DsPIC33
*****
Desconectado Desconectado

Sexo: Masculino
Argentina Argentina

Mensajes: 6757


Con Qt...


WWW
« Respuesta #7 : 17 de Junio de 2011, 20:56:18 »

Lee por aquí: http://www.todopic.com.ar/foros/index.php?topic=25627.0


Saludos!
En línea

EDURET
PIC10
*
Desconectado Desconectado

Costa Rica Costa Rica

Mensajes: 1


« Respuesta #8 : 28 de Octubre de 2011, 18:18:19 »

Hola!!!! Estos días he estado investigando acerca del tema CRC-16 y en particular como se aplica a una línea de texto tal como lo mensionas en tu post...

Justamente eso es lo que ando buscando... Agradecería si tuvieras información y me pudieras compartir.... Soy nuevo en el foro, pero acá es donde he encontrado información valiosisima, y ya llevo días peleandome con esto.

Enserio agradecería cuaquier ayuda!
En línea
Diego E.
Colaborador
PIC24F
*****
Conectado Conectado

Sexo: Masculino
Colombia Colombia

Mensajes: 877



« Respuesta #9 : 01 de Junio de 2012, 17:21:07 »

Hola amigos, ya verifiqué bien, el procedimiento descrito por MGLSOFT está correcto y es fácil de entender, acá pongo el código de una función para calcular el CRC-16 para modbus

Código
GeSHi (c):
  1. #include <16F628a.h>
  2.  
  3. #use delay(clock=4000000, restart_wdt)
  4.  
  5. #byte status = 0x03
  6. #define carry bit_test(status,0)
  7.  
  8. int dato_modbus[9] = {0x01,0x05,0x10,0x00,0x00,0x00,0xc9,0xa0};
  9. long crc_16;
  10.  
  11. long crc_modbus(int dir_buffer, int bytes);
  12.  
  13. ///////////////////////////////////////////////////////////////////////////////
  14. //*****************************************************************************
  15. //*****************************************************************************
  16. //*****************************************************************************
  17. ///////////////////////////////////////////////////////////////////////////////
  18.  
  19. #zero_ram //Borrado de la memoria ram
  20.  
  21. void main()
  22. {
  23.  
  24. while(true)
  25. {
  26. crc_16 = crc_modbus(&dato_modbus[0], 6);
  27. }
  28. }
  29. ///////////////////////////////////////////////////////////////////////////////
  30. long crc_modbus(int dir_buffer, int bytes)
  31. {
  32. int byte_1;
  33. int bit_1;
  34. long res_crc_16 = 0xffff;
  35. for(byte_1=0; byte_1<bytes; byte_1++)
  36. {
  37. res_crc_16 ^= *dir_buffer;
  38. for(bit_1=0; bit_1<8; bit_1++)
  39. {
  40. res_crc_16 = res_crc_16 >> 1;
  41. if(carry)
  42. {
  43. res_crc_16 ^= 0xa001;
  44. }
  45. }
  46. dir_buffer++;
  47. }
  48. return(res_crc_16);
  49. }

Lo comprobé con el On-line CRC calculation and free library

Saludos
« Última modificación: 02 de Junio de 2012, 11:12:34 por Diego E. » En línea

La actitud depende de usted y su entendimiento, la oportunidad de las circunstancias. ¡Su actitud crea circunstancias!
Tirlano
PIC10
*
Desconectado Desconectado

Uruguay Uruguay

Mensajes: 4


« Respuesta #10 : 31 de Julio de 2013, 01:08:32 »

Hola MGLSOFT y demas participantes, queria agradecer vuestra ayuda, me fue de gran utilidad. Un cordial saludo.
En línea
TODOPIC
   

 En línea
Páginas: [1] Imprimir 
« anterior próximo »
Ir a:  

Impulsado por MySQL Impulsado por PHP Powered by SMF 1.1.19 | SMF © 2006-2008, Simple Machines XHTML 1.0 válido! CSS válido!
Página creada en 0.465 segundos con 24 consultas.
anything