Autor Tema: CRC en asm.para el 18fxxxx  (Leído 8517 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
CRC en asm.para el 18fxxxx
« en: 03 de Junio de 2012, 18:42:22 »
hola.estoy con un proyecto para gestionar las tramas del protocolo MODBUS.
ya tengo realizado la recepcion y almacenamiento en la ram del pic de los datos recibidos.pero necesito relizar el calculo del CRC para saber si los datos-
recibidos son correctos.

para ello queria desarroyar la rutina de comprobacion.pero si alguien tiene alguna ya hecha le agradeceria el tiempo que me ahorraria.
en caso contrario si la desarroyo ya la pondria por aqui.gracias de antemano.
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
Re: CRC en asm.para el 18fxxxx
« Respuesta #1 en: 05 de Junio de 2012, 04:44:27 »
bueno.ya esta casi terminado.trabajo me ha costado.me he llevado una alegria cuando he metido los valores de una trama modbus y he visto que los valores
del CRC han coincidido.

es un calculo muy tedioso.desarroyar un programa a partir de un ejemplo en una oja escrita (sin codigo) cuesta un trabajazo.pero os aseguro que la logica
de funcionamiento la tengo bien aprendida.

me he percatado que el CRC se crea despues de cada byte gestionado.y que este se va modificando despues de la gestion del siguiente byte.el calculo del
CRC es infinito si no dejamos de analizar bytes.aunque cuando llegamos al ultimo byte a analizar,el CRC es el ultimo valor que nos da de la gestion de todos
los bytes.

el codigo que he realizado no es muy grande.
no esta terminado del todo.este es infinito.me falta ponerle la finalizacion por localizacion del ultimo byte a leer.
pero se puede probar en un simlador.el CRC es contenido en los registros TEMP_CRCH y TEMP_CRCL.solo hay que poner un break point.despues de haberse guardado los valores del CRC en ellos.la linea tiene la etiqueta CRC1.

los datos a gestionar se cogen a partir de la direccion de memoria 0x20.aunque podemos cambiarlo a la que queramos.

Código: [Seleccionar]
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CALCULO  CRC >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

CRC                                          clrf           FSR1H ;borra puntero FSR
clrf            CONT_CRC ;borra contador de rotaciones
clrf            CONT_CRC2 ;borra contador de datos analizados
setf            CRCH ;pon a 1 todos los bits del registro alto,cotenedor de CRCs (inicializacion)
setf            CRCL ;pon a 1 todos los bits del registro bajo,cotenedor de CRCs (inicializacion)
movlw       0x20 ;valor para primer direccion a leer de la ram.
movwf       FSR1L ;selecciona primera posicion de registros de la ram.

CRC1                                        movff        CRCH,TEMP_CRCH ;intercambia registros principales a temporales.
movff        CRCL,TEMP_CRCL ;intercambia registros principales a temporales.

;separar los nibles de un registro para introducirlos en el nible bajo de otros dos registros.
movff        INDF1,CRCH ;introduce en CRCH valor leido de la ram.
movff        INDF1,CRCL ;introduce en CRCH valor leido de la ram.
swapf        CRCH,F ;invierte los nibles de CRCH.
movlw       0X0F ;valor para conservar el nible bajo.
andwf       CRCH,F ;borra el nible alto.
incf           FSR1L ;incrementa indice de direccionamiento de la ram
movf         TEMP_CRCH,W ;mueve a W el valor alto del valor leido de la ram
xorwf         CRCH,F ;hacer xor con el dato anterior (primera operacion de conversion CRC)
movf          TEMP_CRCL,W ;mueve a W el valor bajo del valor leido de la ram
xorwf        CRCL,F ;hacer xor con el dato anterior (primera operacion de conversion CRC)

CRC2                                        call           ROTAC ;llamada a rutina de conversiones por rotacion.
btfsc         FLAGS,4 ;comprueba si ha habido acarreo en la rotacion.
call          SUM ;llamada a rutina de operacion xor 0xA001 si ha habido acarreo.
CARRY_OFF ;borra flag carry
movlw      0X08 ;valor del contage de movimientos de rotacion
xorwf       CONT_CRC2,w ;comprueba si ha llegado al valor anterior
btfss        STATUS,Z ;si no es asi,
goto         CRC2 ;realiza otra rotacion
clrf          CONT_CRC2 ;en caso contrario reinicia el contador
goto         CRC1 ;vuelve a por el siguiente valor en ram a convertir.

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ROTACIONES >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><

ROTAC                                      incf           CONT_CRC ;incrementa contador de CRC (totales)
incf           CONT_CRC2 ;incrementa contador de 8 contages
rrcf           CRCL,F ;rota CRCL hacia la derecha.
btfsc         STATUS,C ;comprueba si ha habido acarreo
CARRY_ON ;si es asi,activa flag de carry.
bcf            STATUS,C ;borra flag carry del registro STATUS
rrcf           CRCH,F ;rota CRCH hacia la derecha

btfsc          STATUS,C ;comprueba si ha habido acarreo al rotar CRCH
bsf            CRCL,7 ;si es si,poner a 1 el bit alto de CRCL
;btfss          STATUS,C ;comprueba si ha habido acarreo al rotar CRCH
;bcf            CRCH,7 ;si no ha habido acarreo,poner a 1 el bit alto de CRCH
return          ;retorna

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< SUMA DEL VALOR 0XA001 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

SUM                                          movlw       0xA0 ;carga en w el valor 0xA0
xorwf        CRCH,F ;hacer xor con CRCH
movlw       0x01 ;carga en w el valor 0x01
xorwf        CRCL,F ;hacer xor con CRCL
return ;return

segun he visto en algunos documentos.hay dos formas de realizar la comprobacion del CRC.una seria la que he desarroyado.
haciendo el calculo insitu.
y otra seria cogiendo los valores de una tabla.segun dicen los documentos,la opcion de las tablas es mas rapida pero ocupa mas espacio
de rom.
y en la gestion de una trama recibida,la velocidad es un tema bastante importante segun el dispositivo que ballamos a controlar.

por el contrario si la velocidad en la gestion de nuestro dispositivo no es importante.podriamos implementar nuesro codigo
en un chip mas varato.

todo depende de para que lo vayamos a utilizar.

en todo caso primero voy a probar con este codigo.y si veo que es muy lento para mis propositos,tendre que optar por el sistema de
tablas.


como dige anteriormente me falta identificar el ultimo valor a gestionar de la ram.podria poner un caracter de control.pero esto no sirve
porque los valores con los que trabajamos estan todos incluidos.

tambien podria ir buscando el CRC.ya que esta al final de la trama a analizar.pero tampoco puedo porque no sabria en que parte
se encuentra.y me he dado cuenta de que los CRC originales habeces coinciden durante la generacion del CRC a comprobar.

lo ideal es aprovechar el dato de direccion y numero de bytes a enviar de la trama a gestionar.
que estan hubiadas en los 2º,3º y 4º,5º de la trama.

pero aqui se nos presenta otro problema.y es que no todos los codigos de funcion del protocolo MODBUS indican estos valores.
solo se me ocurre discriminar el codigo de funcion y optar en consecuencia.


si alguien tiene otra idea le agradeceria su ayuda.
« Última modificación: 22 de Junio de 2012, 10:48:34 por groundman »
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
Re: CRC en asm.para el 18fxxxx
« Respuesta #2 en: 07 de Junio de 2012, 19:43:04 »
y aqui pongo en programa mejorado:

Código: [Seleccionar]
;Libreria para el calculo y comprobacion del CRC de una tabla de datos ubicada a partir de
;la direccion 0x100h de la ram del pic.
;
;Al llamar a este programa,los datos de la ram son analizados byte a byte.y cuando se leen todos los datos-
;incluidos los dos ultimos bytes (CRC) se comprueva si los CRC recividos,son iguales a los CRC calculados.
;Si los datos recibidos y los calculados son iguales.el bit 1 del registro FLAGS_CRC.indicara si los datos
;son validos o no.siendo valor logico 1=datos correctos y 0=no correctos.
;
;********************************* Ejemplo de codigo a poner en programa principal *********************
; TRAMA_NOK
;SD BTFSC FLAGS_CRC,1
;           NOP           ;aqui saltaria cuando la trama fuera correcta
;           GOTO SD        
;
;*******************************************************************************************************

CBLOCK CRC_VAR
TEMP_CRCL ;primer valor CRC calculado.
TEMP_CRCH ;segundo valor CRC calculado
CRCL ;primer valor CRC calculado.
CRCH ;segundo valor CRC calculado
CONT_CRC ;contador de CRC (totales)
CONT_CRC2 ;contador de 8 contages
CONT_CRC3 ;contador de CRCs producidos
TEMP_FSR0L ;temporal de indice de ram
TEMP_FSR_ANT ;primer valor CRC recivido.
TEMP_FSR_POST ;segundo valor CRC recivido.
TEST ;registro para testado cruzado de CRCs
FLAGS_CRC ;registro de banderas
ENDC
; Definiciones a poner en el programa principal

; #define CARRY_ON bsf FLAGS_CRC,0
; #define CARRY_OFF bcf FLAGS_CRC,0
; #define TRAMA_OK bsf FLAGS_CRC,1
; #define TRAMA_NOK bcf FLAGS_CRC,1

;CRC_VAR EQU 0X50 o la direccion que queramos para introcir los registros

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CALCULO  CRC >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

CRC clrf CONT_CRC ;borra contador de rotaciones
clrf CONT_CRC2 ;borra contador de datos analizados
clrf CONT_CRC3 ;borra contador de CRCs producidos
setf CRCH ;pon a 1 todos los bits del registro alto,cotenedor de CRCs (inicializacion)
setf CRCL ;pon a 1 todos los bits del registro bajo,cotenedor de CRCs (inicializacion)
movlw 0X01 ;valor de direccion del banco 1 de la flash
movwf FSR1H ;selecciona el banco 1 de la eeprom de programa.
clrf FSR1L ;selecciona primera direccion a leer de la ram. (direccion 0100h de la eeprom de programa)

CRC1 movff CRCH,TEMP_CRCH ;intercambia registros principales a temporales.
movff CRCL,TEMP_CRCL ;intercambia registros principales a temporales.

incf CONT_CRC3 ;incrementa contador de CRCs producidos
movf TEMP_FSR0L,W ;carga en w la cantidad de bytes que contiene la trama
xorwf CONT_CRC3,W ;comprueba si coinciden los valores
btfsc STATUS,Z ;si coinciden,
return ;retorna

;separar los nibles de un registro para introducirlos en el nible bajo de otros dos registros.
movff INDF1,CRCH ;introduce en CRCH valor leido de la ram.
movff INDF1,CRCL ;introduce en CRCH valor leido de la ram.
swapf CRCH,F ;invierte los nibles de CRCH.
movlw 0X0F ;valor para conservar el nible bajo.
andwf CRCH,F ;borra el nible alto.
incf FSR1L ;incrementa indice de direccionamiento de la ram
movf TEMP_CRCH,W ;mueve a W el valor alto del valor leido de la ram
xorwf CRCH,F ;hacer xor con el dato anterior (primera operacion de conversion CRC)
movf TEMP_CRCL,W ;mueve a W el valor bajo del valor leido de la ram
xorwf CRCL,F ;hacer xor con el dato anterior (primera operacion de conversion CRC)

;conversiones por rotacion.
CRC2 incf CONT_CRC ;incrementa contador de CRC (totales)
incf CONT_CRC2 ;incrementa contador de 8 contages
rrcf CRCL,F ;rota CRCL hacia la derecha.
btfsc STATUS,C ;comprueba si ha habido acarreo
CARRY_ON ;si es asi,activa flag de carry.
bcf STATUS,C ;borra flag carry del registro STATUS
rrcf CRCH,F ;rota CRCH hacia la derecha
btfsc STATUS,C ;comprueba si ha habido acarreo al rotar CRCH
bsf CRCL,7 ;si es si,poner a 1 el bit alto de CRCL
;btfss STATUS,C ;comprueba si ha habido acarreo al rotar CRCH
;bcf CRCH,7 ;si no ha habido acarreo,poner a 1 el bit alto de CRCH

btfsc FLAGS_CRC,0 ;comprueba si ha habido acarreo en la rotacion.
call SUM ;llamada a rutina de operacion xor 0xA001 si ha habido acarreo.
CARRY_OFF ;borra flag carry
movlw 0X08 ;valor del contage de movimientos de rotacion
xorwf CONT_CRC2,w ;comprueba si ha llegado al valor anterior
bnz CRC2 ;si no es asi realiza otra rotacion
clrf CONT_CRC2 ;en caso contrario reinicia el contador
goto CRC1 ;vuelve a por el siguiente valor en ram a convertir.

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< COMP_CRC >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; compara entre CRC recibido y CRC calculado
COMP_CRC clrf TEST ;borra registro de testado
movf TEMP_CRCH,W ;carga en W el contenido del registro que contiene el primer CRC calculado
cpfseq TEMP_FSR_ANT ;compara si los valores son iguales
incf TEST,F ;incrementa TEST si los valores son diferentes
cpfseq TEMP_FSR_POST ;compara si los valores son iguales al CRC capturado
incf TEST,F ;incrementa TEST si los valores son diferentes

movlw 0x01 ;valor para unica coincidencia detectada
cpfseq TEST ;comparala con registro de testado
return ;si los valores no coinciden retorna

clrf TEST ;borra registro de testado
movf TEMP_CRCL,W ;carga en W el contenido del registro que contiene el primer CRC calculado
cpfseq TEMP_FSR_ANT ;compara si los valores son iguales
incf TEST,F ;incrementa TEST si los valores son diferentes
cpfseq TEMP_FSR_POST ;compara si los valores son iguales al CRC capturado
incf TEST,F ;incrementa TEST si los valores son diferentes

movlw 0x01 ;valor para unica coincidencia detectada
xorwf TEST,W ;comparala con registro de testado
btfsc STATUS,Z ;si los valores coinciden
TRAMA_OK ;activa flag de trama correcta
return ;en caso contrario retorna


;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< SUMA DEL VALOR 0XA001 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

SUM movlw 0xA0 ;carga en w el valor 0xA0
xorwf CRCH,F ;hacer xor con CRCH
movlw 0x01 ;carga en w el valor 0x01
xorwf CRCL,F ;hacer xor con CRCL
return ;return
« Última modificación: 22 de Junio de 2012, 10:49:50 por groundman »
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
Re: CRC en asm.para el 18fxxxx
« Respuesta #3 en: 21 de Junio de 2012, 20:09:57 »
hola de nuevo.resulta que se acaba de presentr un problema con esto de la comprovacion CRC de las tramas.

el programa que he realizado arriva parece ser que funciona bien.pero me ocurre algo raro cuando analizo tramas de 8 bytes de longitud.

esto me pasa en el ejemplo MODBUS del proteus.si analizo tramas de 7 bytes o menos,el isis me las acepta.pero a partir de 8 bytes en adelante.
el CRC de las tramas que se envian entre maestro y esclavo,no corresponden a los calculos de mi programa.

por ejemplo:

la trama 01 04 04 00 00 00 00 fb 84 funciona en el isis.y si analizo esta trama con el programa que he hecho.los datos 01 04 04 00 00 00 00 me da un CRC fb84.

que es correctamente el que le pertenece a la trama.

por contra:

la trama 01 04 00 00 00 00 00 00 60 93 que es la que me da el isis. y funciona entre maestro y esclavo, en mi programa me da un CRC 07c4


segun he visto en algunos manuales de MODBUS.este es un CRC16 y usa un polynominal 0xA001.

no estoy muy seguro si el ejemplo del isis utiliza este polynominal.pero si no lo usa seria imposible que los CRC coincidieran los primeros 7 bytes y no apartir del 8 byte.

en todo caso si nadie sabe si el problema es del isis.alguien me podria indicar una aplicacion para el calculo CRC16 con el polynominal 0XA001 ?

gracias.
« Última modificación: 22 de Junio de 2012, 10:46:55 por groundman »
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: CRC en asm.para el 18fxxxx
« Respuesta #4 en: 21 de Junio de 2012, 20:37:29 »
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
Re: CRC en asm.para el 18fxxxx
« Respuesta #5 en: 22 de Junio de 2012, 04:47:35 »
perdon me he equivocado en la respuesta anterior.el que estoy utilizando es 0xA001.esta en la linea SUM del programa que he subido.

he mirado tu enlace.y es muy interesante.lastima que algunas imagenes ya no esten.de todas formas este tema es algo bastante complicado.y no lo digo
por el sistema de calculo.si no porque el calculo es tan tedioso que no es posible hacerlo a mano si no quieres estar eternamente haciendo calculos.

lo que se es que con solo un bit que nos equivoquemos.los CRC de salida nos saldrian errorneos.entonces.porque a mi me salen bien los calculos comparandolos con el ejemplo del isis hasta el byte 7? y no apartir de ahi?

mi problema es saber si mi programa esta bien hecho.y queria compararlo con algun programa fiable.pero es que los que he visto por la web.no me calculan vien
o no se si los estoy usando mal.

no tendrias algo que no estubiera en C.? he visto una aplicacion para android.pero por mas que meto datos.estos no salen como debieran.

este es el enlace. https://play.google.com/store/apps/details?id=an.CrcCal&hl=es_419
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
Re: CRC en asm.para el 18fxxxx
« Respuesta #6 en: 22 de Junio de 2012, 11:00:45 »
por fin. :-/ :-/ :-/ un dia para encontrar un programa que funcione.

aqui: http://www.lammertbies.nl/comm/info/crc-calculation.html

calcula el CRC de diferentes sistemas.yo pensaba que el CRC16 solo habia un tipo. y no es asi.menosmal que aqui tambien funciona con el polinomio 0xA001
que es el que usa MODBUS.

asi que he hecho los calculos y resulta que mi programa si funciona.al final el CRC de la trama 01040000000000006093 es 0x074 y no 0x6093
como aparece en la trama.

no se que problema habra en el isis.tendre que profundizar haber si doy en el clavo.
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
Re: CRC en asm.para el 18fxxxx
« Respuesta #7 en: 22 de Junio de 2012, 11:27:54 »
 :5] :5] :5] mea culpa  :5] :5] :5]

media semana perdida.el error era mio no del isis.la trama no era la 010400000000006093 sino 0104060000000000006093.
se me olvido poner el deto 06.ahora si me funciona. :lol:

gracias por todo.ya he modificado los errores de las respuestas anteriores.y he quitado un par de lineas que no hacian falta de mi programa.

por cierto.cuando posteo el codigo,salen unos cuadraditos que desfaratan toda la leyenda.se que es por culpa del break space.por eso puse espacios en
el primer codigo.pero es muy tedioso intercambiar los break por espacios.

hay alguna forma de eliminar esos cuadraditos?
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: CRC en asm.para el 18fxxxx
« Respuesta #8 en: 22 de Junio de 2012, 14:42:09 »
Hola.

Pues creo que no hay, al menos no en el foro. Habria que filtrarlo con una aplicación antes de postearlo...

En el enlace que te pase, si descargas el archivo verías que las subrutinas para calculo de CRC estan tanto en C como en ASM...

Me alegro que haya funcionado...

Saludos.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
Re: CRC en asm.para el 18fxxxx
« Respuesta #9 en: 23 de Junio de 2012, 06:29:54 »
gracias.no me di cuenta del enlace.parece que tu codigo es mas compacto que el mio.he intentado adaptarlo al mio.pero entran en cuenta otros valores
del programa principal y no quiero entretenerme mas con mi proyecto.

de todas formas tendria que adaptarle alguna rutina para la lectura de la trama completa.tendria que comprobar si es mas rapido.me interesa la rapidez en la gestion de las tramas.
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
Re: CRC en asm.para el 18fxxxx
« Respuesta #10 en: 30 de Junio de 2012, 08:27:50 »
hay un error en las rutinas anteriores.aqui pongo el programa corregido:

Código: [Seleccionar]
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CALCULO  CRC >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

CRC clrf CONT_CRC ;borra contador de rotaciones
clrf CONT_CRC2 ;borra contador de datos analizados
clrf CONT_CRC3 ;borra contador de CRCs producidos
setf CRCH ;pon a 1 todos los bits del registro alto,cotenedor de CRCs (inicializacion)
setf CRCL ;pon a 1 todos los bits del registro bajo,cotenedor de CRCs (inicializacion)
movlw 0X06 ;valor de direccion del banco 6 de la flash
movwf FSR1H ;selecciona el banco 1 de la eeprom de programa.
clrf FSR1L ;selecciona primera direccion a leer de la ram. (direccion 0600h de la eeprom de programa)

CRC1 movff CRCH,TEMP_CRCH ;intercambia registros principales a temporales.
movff CRCL,TEMP_CRCL ;intercambia registros principales a temporales.

incf CONT_CRC3,f ;incrementa contador de CRCs producidos
movf N_BYTES,W ;carga en w la cantidad de bytes que contiene la trama
xorwf CONT_CRC3,W ;comprueba si coinciden los valores
btfsc STATUS,Z ;si coinciden,
return ;retorna

;separar los nibles de un registro para introducirlos en el nible bajo de otros dos registros.
movff INDF1,CRCL ;introduce en CRCH valor leido de la ram.
clrf CRCH ;poner a cero el registro CRCH.
incf FSR1L,f ;incrementa indice de direccionamiento de la ram
movf TEMP_CRCH,W ;mueve a W el valor alto del valor leido de la ram
xorwf CRCH,F ;hacer xor con el dato anterior (primera operacion de conversion CRC)
movf TEMP_CRCL,W ;mueve a W el valor bajo del valor leido de la ram
xorwf CRCL,F ;hacer xor con el dato anterior (primera operacion de conversion CRC)

;conversiones por rotacion.
CRC2 incf CONT_CRC,f ;incrementa contador de CRC (totales)
incf CONT_CRC2,f ;incrementa contador de 8 contages
rrcf CRCL,F ;rota CRCL hacia la derecha.
btfsc STATUS,C ;comprueba si ha habido acarreo
CARRY_ON ;si es asi,activa flag de carry.
bcf STATUS,C ;borra flag carry del registro STATUS
rrcf CRCH,F ;rota CRCH hacia la derecha
btfsc STATUS,C ;comprueba si ha habido acarreo al rotar CRCH
bsf CRCL,7 ;si es si,poner a 1 el bit alto de CRCL
btfss STATUS,C ;comprueba si ha habido acarreo al rotar CRCH
bcf CRCH,7 ;si no ha habido acarreo,poner a 0 el bit alto de CRCH
btfsc FLAGS_CRC,0 ;comprueba si ha habido acarreo en la rotacion.
call SUM ;llamada a rutina de operacion xor 0xA001 si ha habido acarreo.
CARRY_OFF ;borra flag carry
movlw 0X08 ;valor del contage de movimientos de rotacion
xorwf CONT_CRC2,w ;comprueba si ha llegado al valor anterior
bnz CRC2 ;si no es asi realiza otra rotacion
clrf CONT_CRC2 ;en caso contrario reinicia el contador
goto CRC1 ;vuelve a por el siguiente valor en ram a convertir.
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
Re: CRC en asm.para el 18fxxxx
« Respuesta #11 en: 08 de Febrero de 2015, 20:24:49 »
hola.hace ya tiempo hize la anterior rutina pensando en la cantidad de memoria y no en la velocidad del pic.pero ahora que estoy con el 18F87k22
memoria me sobra.pero requiero mas velocidad.y aunque estoy trabajando a 64Mhz,quiero sacarle el maximo rendimiento al pic.

por eso pongo esta rutina pra el calculo del CRC con polinomio 0xA001 con tablas.



la trama a gestionar se pondria a partir de la direccion 0x600.los registros de proposito general en el banco 7.
el numero de bytes de la trama en N_BYTES.

el resultado sera hubicado en los registros CRCL y CRCH.

espero les sea de utilidad.


Código: [Seleccionar]

#define TABLA_CRCsH 0x5000 ;direccion apartir de donde se metera la tabla alta para el calculo del CRC y rutina de redondeo
#define TABLA_CRCsL 0x5200 ;direccion apartir de donde se metera la tabla alta para el calculo del CRC y rutina de redondeo



;************************************************************** CRC **************************************************
;Calculo del crc por el sistema de tabla.

CRC GENERAL_BANK ;banco de registros de trabajo 0x07 en este caso
setf TEMP_CRCH ;inicializa registros para la generacion del CRC
setf TEMP_CRCL ;inicializa registros para la generacion del CRC
decf N_BYTES,F ;resta uno al contador de rotaciones.
movlw 0X06 ;banco de recepcion de trama
movwf FSR1H ;selecciona el banco de la eeprom de programa.

clrf FSR1L ;inicializa direccionamiento indirecto
next_crc movff INDF1,CRCL ;lee el valor de la trama recibida y lo cargas en registro de CRC bajo
movff TEMP_CRCL,INDEX ;carga valor temporal de CRC alto en indice de tabla
movf CRCL,W ;carga en W el contenido del CRC bajo
xorwf INDEX,F ;hacer xor con CRCL y caga indice de tabla en INDEX

movff INDEX,TBLPTRL ;direcciona tabla
movlw HIGH TABLA_CRCsH;direccion alta de tabla
movwf TBLPTRH ;cargalo en registro
call CRC16 ;busca dato en la tabla alta
xorwf TEMP_CRCH,W ;operacion xor de W con el valor leido de la tabla
movwf TEMP_CRCL ;introduce el resultado en el registro temporal del CRC bajo


movff INDEX,TBLPTRL ;direcciona tabla
movlw HIGH TABLA_CRCsL;direccion baja de tabla
movwf TBLPTRH
call CRC16 ;busca dato en la tabla baja
movwf TEMP_CRCH ;inroduce dato seleccionado de la tabla en el registro temporal CRC alto


incf FSR1L,F ;incementa indice de ram
movf N_BYTES,W ;carga en w la cantidad de bytes que contiene la trama
cpfseq FSR1L
goto next_crc ;siguente byte a leer

movff TEMP_CRCH,CRCH ;actualiza registros
movff TEMP_CRCL,CRCL ;actualiza registros
return ;return


;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CRC16 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


CRC16 clrf WREG ;dato 0x00
xorwf TBLPTRL,w ;comprueba si el dato indexado es igual a 0x00
btfsc STATUS,Z ;si es asi,
goto TABLA_CRC16 ;salta a tabla para leer el primer valor "0"
bcf STATUS,C ;borra el carry
rlcf TBLPTRL,F ;multiplica por 2
bnc TABLA_CRC16 ;salta a tabla si el valor indexado esta en los primeros 256bytes.en caso contrario,
incf TBLPTRH ,f ;incrementa puntero alto de tabla


TABLA_CRC16 tblrd*+ ;incrementa puntero de tabla antes de su lectura
movf TABLAT,W ;carga el valor leido de la tabla en W
return

ORG TABLA_CRCsH ;0x5000

dt 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81
dt 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0
dt 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01
dt 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41
dt 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81
dt 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0
dt 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01
dt 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
dt 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81
dt 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0
dt 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01
dt 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
dt 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81
dt 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0
dt 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01
dt 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
dt 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81
dt 0x40

ORG TABLA_CRCsL ;0x5200

dt 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4
dt 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09
dt 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD
dt 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3
dt 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7
dt 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A
dt 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE
dt 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26
dt 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2
dt 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F
dt 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB
dt 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5
dt 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91
dt 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C
dt 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88
dt 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C
dt 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80
dt 0x40

Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado misterweb

  • PIC16
  • ***
  • Mensajes: 111
Re: CRC en asm.para el 18fxxxx
« Respuesta #12 en: 17 de Febrero de 2015, 17:52:38 »
Interesante, entre uno de mis proyectos pendientes esta la decodificacion de tramas de RDS, y muy seguramente esto me ayude..... asi que :

Gracias.











_______________________________________________________________________________________________________________________________
Mi Blog

https://misterelectronico.wordpress.com/entranador-fabricacion-casera/

Desconectado groundman

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1870
    • www.ingeniopic.com
Re: CRC en asm.para el 18fxxxx
« Respuesta #13 en: 18 de Febrero de 2015, 18:01:28 »
yo no se si RDS utiliza el polinomio 0xA001 para el CRC.tampoco se si este polinomio no es exclusivo solo para  MODBUS.pero para RDS? :shock:
Montando mi primera impresora 3D (Raprep Prusa i3)

Desconectado misterweb

  • PIC16
  • ***
  • Mensajes: 111
Re: CRC en asm.para el 18fxxxx
« Respuesta #14 en: 21 de Febrero de 2015, 08:43:20 »
Perdon groundman por responder un poco tarde, pero es que ultimamente ando un poco liado.

Mas bien que se ajuste o no la tu programa a la decodificacion de la trama de RDS, no mi importa tanto lo que me interesa es el proceso que haces para trabajar con el polinomio.

La forma en que comprueba el error con el decodificador de RDS sigue siendo un tanto oscura para mi.

El RDS se envia en bloques de 26 bits,   16 - 10 bits  , 16 bits son de datos y  10 correscomponden a la correccion de errores.

En el enlace que justo me acabo de encontrar y que no encontre en su dia el siguiente pdf :

 
http://www.google.es/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CDIQFjAA&url=http%3A%2F%2Fwww.eecs.qmul.ac.uk%2F~hamed%2Fpapers%2FRDSencoder.pdf&ei=NG7oVML9EYL7UKiLgogO&usg=AFQjCNFpgK8u784LFseyQEzH62Uf6K-S4Q&bvm=bv.86475890,d.d24


En las paginas 12 y 13 lo explica un poco aunque esta un poco confuso para mi.

Aunque mas adelante pone un ejemplo de como hacerlo, y bueno vere de estudiarlo cuando retome el asunto.

Yo adapte un  TDA7330B  a una radio y saque las tramas y hize un programa en C para adecuarlas, pero al final me canse y lo deje, pero me gustaria retomarlo y montarle un microcontrolador, al ver tu post me recordo esto.

Un saludo groundmand.



______________________________________________________________________________________________________________________________
Mi Blog

https://misterelectronico.wordpress.com/entranador-fabricacion-casera/
« Última modificación: 21 de Febrero de 2015, 08:49:38 por misterweb »


 

anything