Índice general Foros Digital, Electricidad e Informática Codigo asm para PIC, decodificador basico

Codigo asm para PIC, decodificador basico

Moderador: 241-2001


LCS

Desconectado
Mensajes: 93
Registrado: 30 Mar 2011 10:25
Hola, estos días retome un código que hice hace un par de veranos y lo logré hacer funcionar, se trata de un decodificador digital para locomotoras, muy básico pero quiero compartirlo con todos.

La idea es la siguiente toman un Pic lo configuran a su gusto y le ponen este código que en resumen hace lo siguiente:

Son tres fases
-detectar el preámbulo, 12 unos lógicos y espera por el 0 si no empieza de nuevo
-detectar los paquetes de datos, detecta 9 bit (si 9) los aloja en una variable y si el noveno bit es 0 empieza otra variable
si es 1 da por terminada la recepción.
-gestión de datos, pues hace lo que indica, de momento lo mas básico, dirección, velocidad y funciones 1 a 4

La detección del bit se hace por "polling" en la entrada del Pic (A5), pero al salir se repregunta, a modo de asegurar el estado de
la entrada

bucle clrwdt
clrf checksum ;borra la variable que contiene el xor de datos DCC recibidos
bcf flagbyte,7 ;pone a 0 el flag
bcf PORTA,4 ;pone a 0 la salida A4 led de error
movlw 0x0c ;carga W con el valor de 1 logicos minimos a detectar en el preambulo
movwf preamble_count ;lo descarga en la variable preamble_count
preamble_detect
clrwdt ;algoritmo contador duracion de un pulso en A5 3a (58uS)es para saber si dura mas o menos---
clrf valor ;pone a 0 la variable que se usara como contador
btfss PORTA,5 ;comprueba el estado de A5
goto preamble_detect ;no sale mientras no se recibe un bit DCC
dpa clrwdt
incf valor,F ;incrementa la variable
btfsc PORTA,5 ;comprueba el estado de A5
goto dpa ;va a la etiqueta no sale del loop hasta que no acabe el pulso
nop ;5 nop = 1uS 20MHZ xtal 5uS 4 MHZ xtal
nop ;retardo para una segunda lectura
nop ;de la entrada
nop ;
nop ;
btfsc PORTA,5 ;comprueba el estado de A5 sale si realmente fue 0 y no falso contacto
goto dpa ;reitera la consulta de estado del bit para asegurar el dato
movf valor,W ;carga la duracion del pulso en W
bcf STATUS,C ;borra el Carry
sublw 0x0e ;0x41 para 20 MHZ resta una W de una constante de tiempo
btfss STATUS,C ;mira si W era mayor o menor que la constante
goto dpe ;
decfsz preamble_count,F ;al ser menor es 1 logico se decrementa la variable de preamble
goto preamble_detect ;se va a detectar otro bit DCC
bsf flagbyte,7 ;pone a 1 un flag para indicar que se alcanzaron los 1 necesarios de preamble ;
goto preamble_detect ;se va a detectar otro bit DCC-------------------------------------
dpe btfss flagbyte,7 ;comprueba el flag
goto bucle ;error se recibio un 0 sin los 1 necesarios preamble no valido
bcf flagbyte,7 ;pone a 0 el flag
data_detect ;rutina para detectar los bites de datos
movlw (dato1) ;carga el valor offset INDF para el registro FSR
movwf FSR ;INDF apunta a la variable dato1
data_detect2
movlw 0x09 ;bits DCC a detectar 8 + 0 o 1 de fin de paquete
movwf data_count ;variable contador de bit 8+1 fin paquete
movlw 0x03 ;numero maximo de bytes a rellenar
addlw (dato1) ;le suma el offset
bcf STATUS,C ;borra el Carry
subwf FSR,W ;lo resta del FSR
btfsc STATUS,C;
goto signal_error2 ;error por exceso de paquetes 1 de final no recibido
data_detect1
clrwdt
clrf valor ;borra la variable
btfss PORTA,5 ;comprueba el estado de A5
goto data_detect1 ;no sale mientras no se recibe un bit DCC
dpa2 clrwdt
incf valor,F ;incrementa la variable
btfsc PORTA,5 ;comprueba el estado de A5
goto dpa2 ;va a la etiqueta
nop ;5 nop = 1uS 20MHZ xtal
nop ;retardo para una segunda lectura
nop ;de la entrada
nop ;
nop ;
btfsc PORTA,5 ;comprueba el estado de A5 sale si realmente fue 0 y no falso contacto
goto dpa2 ;reitera la consulta de estado del bit para asegurar el dato
decfsz data_count,F ;si es 0 pasa al siguiente byte
goto data_detect4 ;va a recibir un bit DCC
goto data_detect3 ;va a rellenar el siguiente byte
data_detect4
movf valor,W ;carga la duracion del pulso en W
rlf INDF,F ;rota a la izquierda para el siguiente bit
bcf STATUS,C ;borra el Carry
sublw 0x0e ;0x41 para 20 MHZ resta una constante de tiempo a W
bcf INDF,0 ;pone a 0 la variable
btfsc STATUS,C ;mira si W era mayor o menor que la constante
bsf INDF,0 ;pone a 1 el bit DCC en la variable
goto data_detect1 ;
data_detect3
movf valor,W ;carga la duracion del pulso en W
bcf STATUS,C ;borra el Carry
sublw 0x0e ;0x41 para 20 MHZ resta una constante de tiempo a W
btfsc STATUS,C ;mira si W era mayor o menor que la constante
goto gestion_datos ;
movf INDF,W ;carga W con el byte recibido
xorwf checksum,F ;hace un xor para hacer el checksum
incf FSR,F ;incrementa el puntero FSR
goto data_detect2 ;
gestion_datos
movlw (dato3) ;carga en W el puntero de la variable que contiene el checksum
movwf FSR ;decrementa el puntero FSR para apuntar al ultimo dato recibido
movf INDF,W ;carga W con el ultimo dato recibido
subwf checksum,W ;resta el checksum del checksum recibido
btfss STATUS,Z ;si es 0 se recibio todo bien
goto signal_error3;se?aliza error
movf dato1,F ;comprueba si es la direccion 0
btfsc STATUS,Z ;si no es 0 continua comprobando la direccion DCC
goto adv ;la direccion 0 la deben atender todos los decodificadores DCC
movf dcc_adr,W ;carga W dcc_adr = direccion addreses del decodificador DCC
subwf dato1,W ;dcc_adr decoder - DCC byte = 0 OK se procesan los datos
btfss STATUS,Z ;si lo es salta y ejecuta el codigo para hacer el tratamiento de los datos recibidos
goto bucle ;la variable dato1 addresses no es la del decodificador entonces vuelve al principio
adv movlw 0x01 ;carga el PCLATH con 1 para asegurar el computed goto correcto
movwf PCLATH ;
swapf dato2,W ;intercambia nibbles
movwf resultado ;deja W en la variable temporal
rrf resultado,F ;rota una posicion a la derecha
movlw 0x07 ;carga W con la mascara para dejar solo los bit 7,6,5 (nibbles intercambiados)
andwf resultado,W ;hace el and y lo deja en W
salto addwf PCL,F ;suma el resultado al PCL para hacer un computed goto
goto control_in ;0 va a la rutina de gestion Decoder Control Instruccion
goto operacion_in;1 va a la rutina de gestion Advanced Operation Instruccion
goto reverse_op ;2 va a la rutina de gestion velocidad y marcha atras
goto forward_op ;3 va a la rutina de gestion velocidad y marcha adelante
goto funcion_0_4 ;4 va a la rutina de gestion activacion de las funciones de la 0 a la 4
goto funcion_5_12;5 va a la rutina de gestion activacion de las funciones de la 5 a la 12
goto f_expansion ;6 va a la rutina de gestion futura s expansiones
goto cv_instruccion ;7 CV Configuracion Variable access Instruccion
goto bucle ;8
goto bucle ;9
goto bucle ;a
goto bucle ;b
goto bucle ;c
goto bucle ;d
goto bucle ;e
goto bucle ;f
control_in
goto bucle
operacion_in
goto bucle
reverse_op
btfsc CCP1CON,P1M1 ;comprueba el cambio de sentido de marcha
goto frenado_auto
bcf flagbyte,5 ;indica la marcha atras
bcf CCP1CON,P1M1 ;pone a 0 el bit del PWM reverse
goto pwm_v ;va a cargar el PWM duty cycle
forward_op
btfss CCP1CON,P1M1 ;comprueba el cambio de sentido de marcha
goto frenado_auto ;va a la secuencia de frenado automatico
bsf flagbyte,5 ;indica la marcha adelante
bsf CCP1CON,P1M1 ;pone a 1 el bit del PWM
pwm_v
movf dato2,W ;carga W con el valor de velocidad
movwf v_general2 ;descarga W para modificar la variable y pasar el bit 4 al bit 0
rlf v_general2,F ;hace 4 rotaciones para pasar el bit 4 al CARRY
rlf v_general2,F ;
rlf v_general2,F ;
rlf v_general2,F ;
swapf v_general2,F ;intercambia nibbles
rlf v_general2,W ;ahora tenemos los bit 4,3,2 mas el bit 0 que antes era el 4
andlw 0x1f ;hace un and para dejar solo los bit de velocidad
movwf CCPR1L ;los descarga en la variable y luego al Duty Cycle del PWM en el bucle principal
rlf CCPR1L,F ;multiplica por 2 el DUTY CYCLE
rlf CCPR1L,F ;multiplica por 2 el DUTY CYCLE
movwf v_general2 ;los descarga en el registro para saber si es 0
bcf STATUS,C ;borra el CARRY
rrf v_general2,F ;desplaza a la derecha para saber si es 0 (valores 0 y 1 STOP)
movf v_general2,F ;si es 0 ejecuta el codigo de parada
btfss STATUS,Z ;
goto bucle
clrf CCPR1L ;pone a 0 el PWM
goto bucle
frenado_auto
movlw 0x80 ;mascara para conmutar el bit 7 PM1 direccion forw/revr
xorwf CCP1CON,W ;carga el bit
movwf CCP1CON ;lo descarga conmutado
clrf CCPR1L ;reduce a 0 el DUTY CYCLE
call delay ;produce un retardo para no invertir el motor demasiado rapido
call delay ;produce un retardo para no invertir el motor demasiado rapido
call delay ;produce un retardo para no invertir el motor demasiado rapido
call delay ;produce un retardo para no invertir el motor demasiado rapido
goto bucle ;
funcion_0_4
bsf PORTB,1 ;pone a 0 la salida 1
btfss dato2,0 ;si el bit de la variable esta a 1 activa bit en el PUEROB
bcf PORTB,1;pone a 1 el bit del PUERTOB Funcion 1
bsf PORTB,2 ;pone a 0 la salida 2
btfss dato2,1 ;si el bit de la variable esta a 1 activa bit en el PUEROB
bcf PORTB,2;pone a 1 el bit del PUERTOB Funcion 2
bsf PORTB,4 ;pone a 0 la salida 4
btfss dato2,2 ;si el bit de la variable esta a 1 activa bit en el PUEROB
bcf PORTB,4;pone a 1 el bit del PUERTOB Funcion 3
bsf PORTB,5 ;pone a 0 la salida 5
btfss dato2,3 ;si el bit de la variable esta a 1 activa bit en el PUEROB
bcf PORTB,5;pone a 1 el bit del PUERTOB Funcion 4
bcf PORTB,6 ;pone a 1 la salida B6 FL en avance
bcf PORTB,7 ;pone a 1 la salida B7 FL en marcha atras
btfss dato2,4 ;si el bit de la variable esta a 1 activa bit en el PUEROB
goto bucle ;si la funcion FL no activada sale
btfss flagbyte,5 ;comprueba la direccion
bsf PORTB,7 ;pone a 0 la salida B7 FL en marcha atras
btfsc flagbyte,5 ;comprueba la direccion
bsf PORTB,6 ;pone a 0 la salida B6 FL en avance
goto bucle
funcion_5_12
goto bucle
f_expansion
goto bucle
cv_instruccion
goto bucle

LCS

Desconectado
Mensajes: 93
Registrado: 30 Mar 2011 10:25
Bueno parece que al no quedar bien tabulado se hace difícil de comprender, pero en el fondo es mas sencillo de lo que parece, si lo copian en MPLABX, o su herramienta de programación favorita con colorines mejora bastante.

El Pic es un 16F690, y el 99% de las lineas esta comentada con lo que hace, aunque sea obvio.


Desconectado
Mensajes: 625
Ubicación: Asturias
Registrado: 15 Nov 2012 19:16
Hola LCS,

¡qué bien!, por fin alguien más con inquietudes electrónicas. No soy muy amigo de los pics (soy más del 8051 y ahora voy a por los AVR) pero me parece interesante el compartir un programa. Quiero hacerte una pregunta: si dices que funciona correctamente ¿es porque hay algún circuito en el que lo hayas probado?; te pediría que lo compartieras; además sería un buen decodificador de locomotoras que podría animar a algún forero a realizarlo. ¿Sería programable?, me refiero a poder cambiarle la dirección con un programador.

Gracias,

Germán


Desconectado
Mensajes: 330
Registrado: 22 Feb 2011 13:45
Hola LCS.

Te puedes poner en contacto conmigo por Email ?. Mi correo es: furdex @ gmail punto com

Saludos.

LCS

Desconectado
Mensajes: 93
Registrado: 30 Mar 2011 10:25
Hola, mi intención era hacerme mis propios decoder, que como ya sabéis sale mas caro que comprarlos, pero me lo tome como un reto y un miserable bit me ha vuelto loco 1 año, y es que no borraba el flag C de acarreo por lo cual los paquetes de datos se rellenaban con 1 y no con el bit recibido.

El decoder atiende a la dirección 0 y a la que este grabada en la primera posición eeprom, no atiende a valores de inercia ni nada parecido, tan solo lo básico funciones 1 a 4 foco en función de marcha, velocidad 28 pasos y frenada de emergencia. Aún así el código si "parsea" otras funciones pero están vacías de código, eso queda en manos de las necesidades de cada uno.

El esquema esta hecho con el programa eagle, y el prototipo esta hecho en tamaño grande y cabe dentro de la 333 de Roco, se basa en un PIC 16F690 y un L272M como puente H para el motor, las luces van con transistores BC547, un rectificador un 78l05 y componentes discretos.

LCS

Desconectado
Mensajes: 93
Registrado: 30 Mar 2011 10:25
Una imagen para ilustrar
Adjuntos
060920131461.jpg


Desconectado
Mensajes: 330
Registrado: 22 Feb 2011 13:45
Hola LCS:

Te iba a preguntar si el código lo has sacado de la página de Cote. Ahora mismo, NO tengo al alcance de la mano el software de Cote. No obstante, creo que NO. No debe de ser el mismo. Vamos, seguro que NO es el mismo, puesto que la estación digital de Cote, puede variar el código del decoder al que van dirigidas las instrucciones digitales.

No obstante, se me plantea la duda ?. Sería posible hacer el código para PC (80x86) ?. Este micro(procesador), aunque mucho más potente que el 16f84 (o familia microchip), tiene la ventaja (para quien no disponga de medios para la electrónica y sepa programación), que sólo necesita el compilador para ASM del 80x86, un editor, conocimientos y......paciencia. Lo digo porque profesionalmente, los programas realizados en ENSAMBLADOR, además de ser más veloces que los realizdas en BASIC, por ejemplo, además de esto, ocupan como mínimo más de 4 o 5 mil linas.

Saludos.


Desconectado
Mensajes: 330
Registrado: 22 Feb 2011 13:45
Hola Amando.

Estoy dándole vueltas a la idea de hacer un software para PC que convierta el ordenador en una central digital, de modo que éste funcione sin necesidad de Windows, puertos virtuales ni drivers (por ejemplo, en MS-DOS). Para ello, voy a hacerlo en lenguaje Ensamblador a través de una de la patas que suministra la RS-232 (por ejemplo, la pata 5 del DB9).

Sólo preciso el esquema mediante el cual se suministraría la señal de onda cuadrada que iría por la vía y decodificaría el decoder de la máquina (dreo que tú en tu hilo lo denominaste “pooling”. Quisiera que me lo confirmaras para buscarlo, si es caso, yo mismo por Internet).

Me puedes echar una mano ?. Te lo agradecería.

Para cualquier dato técnico, puedes ponerte en contacto conmigo. Bien por este medio, por privado o directamente por Email.

Gracias.

Saludos.

LCS

Desconectado
Mensajes: 93
Registrado: 30 Mar 2011 10:25
Si el polling es leer una entrada a tiempos regulares hasta que cambia de estado.
Lo que necesitas es un booster, el de la estación digital esta basado en el chip LM18200T, es el que tengo yo, pero hay muchas opciones,
La salida 5 del DB9 habría que aplicarle algún optoacoplador porque me parece que trabaja a -12v tengo que mirarlo.


Desconectado
Mensajes: 330
Registrado: 22 Feb 2011 13:45
A lo tuyo se llama rapidez.

Tienes conectado tu Email, quizás al Messenger ?.

Si. Efectivamente. Creo que la RS-232 trabaja a -12 V. Habría que meter quizás un MAX232, que me parece que hace la conversión.

De todas formas, esa pata sabes que puede estar a 1 o 0 binario. A uno debe de generar señales cuadradas de 116 uS aproximadamente en el caso del 0. Y en el caso del 1, el periodo aproximado debe de ser de 58 uS.

Una cadena de secuencia de 1 sg. en la vía sería como muestro en el dibujo.

Siendo el periodo del 0, el doble que el del 1.

Saludos.
Adjuntos
paquete_en_via.jpg


Volver a Digital, Electricidad e Informática

Síguenos en Facebook Síguenos en Youtube Síguenos en Instagram Feed - Nuevos Temas
©2017   -   Información Legal
cron