Dudas para crear temporizador en ensamblador

Iniciado por Fox_Neo, 20 Marzo 2013, 10:15 AM

0 Miembros y 1 Visitante están viendo este tema.

Fox_Neo

Hola quiero crear un temporizador con el PIC P16F886, de 0,5 segundos de pulso osea con una frecuencia de 1Hzy no se como programarlo , tengo la idea pero no se plasmarlo en emsalblador. Os explico:
Voy a usar el oscilador interno del PICde 4MHz lo que es lo mismo con un periodo de 0,25us si una instruccion tarda 4 ciclos de reloj, cada instrucción tarda en ejegutarse 1us.
Tengo que conseguir que oscile a 0,5s--> 500.000us para ello quiero poner el TMR0 inicialmente a 250 y el preescale a 8 con lo que el TMR0 se desborda cada 2000us  (250*8=2000). Si con un contador cuento 250 vecesda 0,5 s (2000us*250=500.000us=0.5s).
Lo que no se hacer o que no entiendo como se le da la orden de que empie a contar  otra cosa que no entiendo es que al ir comparando el valor del contador cuenta como un tiempo de instrucción por tanto ya se retrasaria, no se tengo un cacao muy grande,
se que tengo cuando se supere el desbordamiento del TMR0  cada 2000us tengo que poner el bit TI0IF del registro INTCON  mediante programa a 0.   

Aqui os dejo un diagrama de como creo que funciona:

Gracias

Meta

Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

Fox_Neo

Gracias Meta por la ayuda, umm lo único que he sabido hacer es configurar los puertos:
Código (asm) [Seleccionar]
;***** CONFIGURACIÓN ******************************************************
List p=16F886 ;Tipo de procesador
include "P16F886.INC" ;Definiciones de registros internos
;Ajusta los valores de las palabras de configuración durante el ensamblado.Los bits no empleados
;adquieren el valor por defecto.Estos y otros valores se pueden modificar según las necesidades

__config _CONFIG1, _LVP_OFF&_PWRTE_ON&_WDT_OFF&_EC_OSC&_FCMEN_OFF ;Palabra 1 de configuración
__config _CONFIG2, _WRT_OFF&_BOR40V

; _MCLRE_ON: Reset externo ACTIVADO.
; _CP_OFF: Protección del código DESACTIVADO.
; _WDT_OFF: Watchdog DESACTIVADO.
; _IntRC_OSC: Oscilador interno de 4MHz.
;***** DEFINICIÓN DE VARIABLES
; Definimos las posiciones de memoria de los datos
CONTADOR equ 0x10
;**************************************************************************
; Inicialización del programa:
; Origen
Org 0x00
goto Inicio ;Vector de reset
org 0x05
; Configuración de los puertos como entradas y salidas
Inicio clrf PORTB ; Borrado de los biestables de salida
bsf STATUS,RP0 ; Selecciona banco 3 (RP0=RP1='1')
bsf STATUS,RP1
clrf ANSEL ; El puerto A de tipo digital
clrf ANSELH ; El puerto B de tipo digital
bcf STATUS,RP1 ; Selecciona banco 1 (RP1='0' RP0='1')
clrf TRISB ; RB7:RB0 se configuran como salidas
movlw b'00111111'
movwf TRISA ; RA5:RA0 se configuran como entrada
movlw b'00000110' ;movemos el valor de la opción del preescale  al registro W
movwf OPTION_REG ;pasamos el valor de w al registro
bcf STATUS,RP0 ; Se vuelve al banco 0
movlw b'00000111' ;movemos el valor de la opción del preescale  al registro W
movwf INTCON ;

ya más no se estoy bastante perdido :S
Gracias[/size]

Meta

Hola:

Aquí encontré un ejemplo sencillo.
Código (asm) [Seleccionar]
;El Timer 0 TMR0.
;
;Se trata de comprobar el funcionamiento básico del Timer 0. Cuando se detecta un flanco
;decendente en RA0 (conectada con un pulsador), se activa la salida RB0 durante un tiempo
;y luego se desconecta. El TMR0 realiza una temporización de 50mS que se repite tantas veces
;como se indique en la variable "Temp". Así pues la temporización total será de 50mS*Temp.
;
;Suponiendo una frecuencia de trabajo de 4MHz, 4Tosc=1uS. Trabajando con un prescaler de 256,
;al TMR0 hay que cargarlo con 195 para temporizar 50mS (Temporización=1uS*195*256)


List p=16F886 ;Tipo de procesador
include "P16F886.INC" ;Definiciones de registros internos

;Ajusta los valores de las palabras de configuración durante el ensamblado.Los bits no empleados
;adquieren el valor por defecto.Estos y otros valores se pueden modificar según las necesidades

__config _CONFIG1, _LVP_OFF&_PWRTE_ON&_WDT_OFF&_EC_OSC&_FCMEN_OFF&_BOR_OFF ;Palabra 1 de configuración
__config _CONFIG2, _WRT_OFF&_BOR40V ;Palabra 2 de configuración

Valor equ .20 ;Constante para temporizar 1 seg (50mS*20)

Temp equ 0x020 ;Variable para la temporización
             
org 0x00 ;Vector de RESET
goto Inicio
org 0x05

;*********************************************************************************************
;Delay: El Timer 0 realiza un retardo de 50mS que se repite tantas veces como se indica en la
;constante valor

Delay movlw Valor
movwf Temp ;Nº de veces a temporizar 50 mS
Delay_1 movlw ~.195 
movwf TMR0 ;Inicia el Timer 0 con 195 (195*256=49.9mS)
bcf INTCON,T0IF ;Repone flag del TMR0
Delay_2 btfss INTCON,T0IF ;Fin de los 50mS ??
goto Delay_2 ;No, el TMR0 no ha terminado
decfsz Temp,F ;Decrementa el contador. Fin de temporización ??
            goto Delay_1 ;No, el TMR0 temporiza otros 50 mS
return ;Si, final de la temporización

;Programa principal
Inicio clrf PORTB ;Borra los latch de salida
bsf STATUS,RP0
bsf STATUS,RP1 ;Selecciona banco 3
clrf ANSEL ;Puerta A digital
clrf ANSELH ;Puerta B digital
bcf STATUS,RP1 ;Selecciona banco 1
movlw b'11111110'
movwf TRISB ;RB0 se configura como salida
movlw b'00111111'
movwf TRISA ;RA5:RA0 se configuran como entrada
movlw b'00000111'
movwf OPTION_REG ;TMR0 con reloj interno y preescaler de 256
bcf STATUS,RP0 ;Selecciona banco 0                                                                          

;Este es el cuerpo principal del programa. Espera a que en RA0 se detecte un flanco descendente

Loop btfsc PORTA,0     ;RA0=0 ??
            goto Loop ;No, esperar
bsf PORTB,0 ;Si activar RB0
call Delay ;Temporizar
bcf PORTB,0 ;Desactivar RB0
goto Loop ;Repetir el proceso

end



Otro más por aquí.
Código (asm) [Seleccionar]
;La interrupción del TMR0.
;
;Se trata de comprobar la interrupción provocada por el TMR0. El programa
;lee el estado de los interruptores conectados a RA0 y RA1 para reflejarlo en
;los leds conectados a RB0 y RB1 respectivamente. Al mismo tiempo el TMR0
;genera una interrupción cada 0.01 seg. (10 mS) que se repetirá 50 veces con objeto
;de hacer intermitencia de 500 mS sobre el led conectado a RB3.


List p=16F886 ;Tipo de procesador
include "P16F886.INC" ;Definiciones de registros internos

;Ajusta los valores de las palabras de configuración durante el ensamblado.Los bits no empleados
;adquieren el valor por defecto.Estos y otros valores se pueden modificar según las necesidades

__config _CONFIG1, _LVP_OFF&_PWRTE_ON&_WDT_OFF&_EC_OSC&_FCMEN_OFF&_BOR_OFF ;Palabra 1 de configuración
__config _CONFIG2, _WRT_OFF&_BOR40V ;Palabra 2 de configuración

Contador equ 0x020 ;Variable para la temporización
             
org 0x00 ;Vector de RESET
goto Inicio
org 0x04 ;Vector de interrupción
goto Interrupcion
org 0x05

Interrupcion    bcf INTCON,T0IF ;Repone flag del TMR0
decfsz Contador,F ;Decrementa el contador. Ha habido 50 interrupciones ??
            goto Seguir ;No, no han pasado los 500 mS
Con_si_0    movlw .50
            movwf Contador    ;Repone el contador nuevamente para contar 50 interrupciones
            movlw b'00001000'
xorwf PORTB,F ;RB3 cambia de estado
Seguir    movlw ~.39
            movwf TMR0      ;Repone el TMR0 con 39
            retfie ;Retorno de interrupción

Inicio clrf PORTB ;Borra los latch de salida
bsf STATUS,RP0
bsf STATUS,RP1 ;Selecciona banco 3
clrf ANSEL ;Puerta A digital
clrf ANSELH ;Puerta B digital
bcf STATUS,RP1 ;Selecciona banco 1
clrf TRISB ;RB7:RB0 se configuran como salida
movlw b'00111111'
movwf TRISA ;RA5:RA0 se configuran como entrada
movlw b'00000111'
movwf OPTION_REG ;Preescaler de 256 para el TMR0
bcf STATUS,RP0 ;Selecciona banco 0                                                                          

;El TMR0 se carga con 39. Con un preescaler de 256 y a una frecuencia de 4MHz se obtiene una interrupción
;cada 10mS. Se habilita la interrupción del TMR0.

movlw ~.39
movwf TMR0 ;Carga el TMR0 con 39
movlw .50
movwf Contador ;Nº de veces a repetir la interrupción
movlw b'10100000'
movwf INTCON ;Activa la interrupción del TMR0

;Este es el cuerpo principal del programa. Consiste en leer constantemente el estado de RA0 y RA1 para visualizar
;sobre RB0 y RB1 sin que cambie el estado actual de RB7

Loop btfsc PORTA,0     ;Testea el estado de RA0
            goto RA0_ES_1
            bcf PORTB,0 ;Desactiva RB0
            goto TEST_RB1
RA0_ES_1    bsf PORTB,0 ;Activa RB0
TEST_RB1    btfsc PORTA,1     ;Testea el estado de RA1
            goto RA1_ES_1
            bcf PORTB,1 ;Desactiva RB1
            goto Loop
RA1_ES_1  bsf PORTB,1 ;Activa RB1
goto Loop

end ;Fin del programa fuente


Saludo.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

Fox_Neo

Muchas garcias Meta por la ayuda creo que estoy avanzando hasta ahora llevo lo siguiente, me falta poner que cuando el contador de usuario llegue a 0 se active la salida:
Código (asm) [Seleccionar]
;**************************************************************************
;***** CONFIGURACIÓN ******************************************************
List p=16F886 ;Tipo de procesador
include "P16F886.INC" ;Definiciones de registros internos
;Ajusta los valores de las palabras de configuración durante el ensamblado.Los bits no empleados
;adquieren el valor por defecto.Estos y otros valores se pueden modificar según las necesidades

__config _CONFIG1, _LVP_OFF&_PWRTE_ON&_WDT_OFF&_EC_OSC&_FCMEN_OFF ;Palabra 1 de configuración
__config _CONFIG2, _WRT_OFF&_BOR40V

; _MCLRE_ON: Reset externo ACTIVADO.
; _CP_OFF: Protección del código DESACTIVADO.
; _WDT_OFF: Watchdog DESACTIVADO.
; _IntRC_OSC: Oscilador interno de 4MHz.
;***** DEFINICIÓN DE VARIABLES
; Definimos las posiciones de memoria de los datos
CONTADOR equ 0x20
;**************************************************************************
; Inicialización del programa:
; Origen
Org 0x00
goto Inicio ;Vector de reset
org 0x05
; Configuración de los puertos como entradas y salidas
Inicio clrf PORTB ; Borrado de los biestables de salida
bsf STATUS,RP0 ; Selecciona banco 3 (RP0=RP1='1')
bsf STATUS,RP1
clrf ANSEL ; El puerto A de tipo digital
clrf ANSELH ; El puerto B de tipo digital
bcf STATUS,RP1 ; Selecciona banco 1 (RP1='0' RP0='1')
clrf TRISB ; RB7:RB0 se configuran como salidas
movlw b'00111111'
movwf TRISA ; RA5:RA0 se configuran como entrada
movlw b'00000010' ;movemos el valor de la opción del preescale  al registro W EN ESTE CASO A 8
movwf OPTION_REG ;pasamos el valor de w al registro
bcf STATUS,RP0 ; Se vuelve al banco 0
movlw b'00000111' ;movemos el valor de la opción del preescale  al registro W
movwf INTCON
; Fin de la inicialización del programa.

empezar MOVLW .250 ;INICIALIZAR CONTADOR
MOVWF CONTADOR

esperar BTFSS PORTA,0 ;comprobamos si en interuptor esta en ON
GOTO esperar
MOVLW d'5' ;INICIALIZAR TMR0 A 5 PARA QUE CUENTE HASTA 250 YA QUE DESBORDA A 256 para simular x ejemplo poner 252
MOVWF TMR0 ;CARGA EL VALOR DE 5 EN TMR0
CLRF INTCON ;POR SI MIENTRAS SE ESPERABA A QUE SE ACTIVARA EL INTERRUPTOR SE HA DESBORDADO
esperardes BTFSS INTCON,T0IF ;VERIFICAMOS CUANDO LLEGA A 256 MEDIANTE EL BIT 2  DEL REGISTRO INTCON
GOTO  esperardes ;SI NO ES UNO HAY QUE ESPERAR
CLRF INTCON ;SE HA ALCANZADO DESBORDAMIENTO HAN PASADO 2000us SE BORRA EL DESBORDAMIENTO
DECFSZ CONTADOR,1 ;COMPROBAR QUE EL CONTADOR HA LLEGADO A 0 CUANDO OCURRE SALTA UNA INSTRUCCION
GOTO esperar
GOTO empezar ;EL CONTADOR ESTA A 0 , YA HAN PASADO 0,5 SEGUNDOS
end


¿Como lo veis de momento?  :)

Gracias por la ayuda.[/size]

Fox_Neo

Bueno por fin lo he conseguido  me ha costado lo suyo pero lo he conseguido  ;D
aqui esta:

Código (asm) [Seleccionar]
;***** CONFIGURACIÓN ******************************************************
List p=16F886 ;Tipo de procesador
include "P16F886.INC" ;Definiciones de registros internos
;Ajusta los valores de las palabras de configuración durante el ensamblado.Los bits no empleados
;adquieren el valor por defecto.Estos y otros valores se pueden modificar según las necesidades

__config _CONFIG1, _LVP_OFF&_PWRTE_ON&_WDT_OFF&_EC_OSC&_FCMEN_OFF ;Palabra 1 de configuración
__config _CONFIG2, _WRT_OFF&_BOR40V

; _MCLRE_ON: Reset externo ACTIVADO.
; _CP_OFF: Protección del código DESACTIVADO.
; _WDT_OFF: Watchdog DESACTIVADO.
; _IntRC_OSC: Oscilador interno de 4MHz.
;***** DEFINICIÓN DE VARIABLES
; Definimos las posiciones de memoria de los datos
CONTADOR equ 0x20
AUX equ 0x21
;**************************************************************************
; Inicialización del programa:
; Origen
Org 0x00
goto Inicio ;Vector de reset
org 0x05
; Configuración de los puertos como entradas y salidas
Inicio clrf PORTB ; Borrado de los biestables de salida
bsf STATUS,RP0 ; Selecciona banco 3 (RP0=RP1='1')
bsf STATUS,RP1
clrf ANSEL ; El puerto A de tipo digital
clrf ANSELH ; El puerto B de tipo digital
bcf STATUS,RP1 ; Selecciona banco 1 (RP1='0' RP0='1')
clrf TRISB ; RB7:RB0 se configuran como salidas
movlw b'00111111'
movwf TRISA ; RA5:RA0 se configuran como entrada
movlw b'00000010' ;movemos el valor de la opción del preescale  al registro W EN ESTE CASO A 8
movwf OPTION_REG ;pasamos el valor de w al registro
bcf STATUS,RP0 ; Se vuelve al banco 0
movlw b'00000111' ;movemos el valor de la opción del preescale  al registro W
movwf INTCON
; Fin de la inicialización del programa.

;______________________________ACTIVACIÓN INICIAL DE LA SALIDA_________________________________________________________
ESPERAR BTFSS PORTA,0 ;PRIMERA VEZ QUE SE VA A VER SI ESTA ACTIVADO EL INTERUPTOR
GOTO ESPERAR
MOVLW b'0000001' ;SE ACTIVA LA SALIDALA PRIMERA VEZ QUE SE PONE EL INTERRUPTOR
MOVWF  PORTB
MOVLW 0X01 ;INICIALIZO EL REGISTRO AUX PARA INDICAR QUE SE HA ACTIVADO EL INTERRUPTOR
MOVWF AUX
;__________________________________________________________________________________________________________
empezar
MOVLW .2 ;INICIALIZAR CONTADOR A 250 PARA SIMULAR PONER EL CONTADOR A 2
MOVWF CONTADOR

esperar2
CALL COMP_ENTRADA ;COMPRUEBA EL ESTADO DE LA ENTRADA
BTFSS AUX,0 ;SI EL RESULTADO DE LA LLAMADA HA DADO 0 NO SE SALTA UNA INSTRUCCIÓN POR TANTO TIENE QUE REINICIARSE EL PROGRAMA
GOTO ESPERAR
MOVLW d'252' ;INICIALIZAR TMR0 A 5 PARA QUE CUENTE HASTA 250 YA QUE DESBORDA A 256 para simular x ejemplo poner 252
MOVWF TMR0 ;CARGA EL VALOR DE 5 EN TMR0
CLRF INTCON ;POR SI MIENTRAS SE ESPERABA A QUE SE ACTIVARA EL INTERRUPTOR SE HA DESBORDADO
esperardes BTFSS INTCON,T0IF ;VERIFICAMOS CUANDO LLEGA A 256 MEDIANTE EL BIT 2  DEL REGISTRO INTCON CUANDO LLEGA SE DESBORADA DANDO UN 1
GOTO  esperardes ;SI NO ES 1 HAY QUE ESPERAR
CLRF INTCON ;SE HA ALCANZADO DESBORDAMIENTO HAN PASADO 2000us SE BORRA EL DESBORDAMIENTO
DECFSZ CONTADOR,1 ;COMPROBAR QUE EL CONTADOR HA LLEGADO A 0 CUANDO OCURRE SALTA UNA INSTRUCCION
GOTO esperar2
GOTO activarsal ;EL CONTADOR ESTA A 0 , YA HAN PASADO 0,5 SEGUNDOS
activarsal
MOVLW b'0000001'
XORWF  PORTB,F ;INVIERTE EL VALOR DE LA SALIDA
GOTO empezar

;_______________________SUBRUTINAS________________________________________________

COMP_ENTRADA NOP
esperar3 BTFSS PORTA,0
GOTO SALIDA0
RETURN

SALIDA0 CLRF PORTB
CLRF AUX ;AL APAGAR EL INTERUPTOR EN MITAD DEL PROCESO ENTRA AQUI  Y SEÑALO CON UN 0 QUE SE HA APAGADO EN INTERRUPTOR ES COMO EN C PONER EL RESULTADO DE UNA FUNCIÓN
GOTO esperar3


end


Gracias por la ayuda, si veis algo que se puede mejorar o reducir el programa me gustaría saberlo o si veis algún fallo.
Salu2 

Meta

Hola:

Puedes comprobarlo con un simulador de PIC como el Proteus 7.10.

Saludo.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

Firos

Si ya has conseguido que funcione ahora podrías perfeccionarlo.


Cuando comprobamos si un interruptor está a "1" o a "0" hay que eliminar rebotes.

Es decir, cualquier modo de contacto piezoeléctrico al hacer que conecten sus dos "bornes" hay ahí un "ruido" que en ocasiones puede ser que realmente el interruptor no esté a "1" o que en cuanto le des el contador automáticamente se detenga (en caso de que cuando detecte cero se pare).


Por esto mismo te recomiendo que hagas una cosa. Hazte una subrutina de retardos, como la que tienes de 0,5 segundos en este mismo hilo pero con muchas otras de 20 milisegundos, 50 milisegundos, 100 milisegundos, etc, etc.

Para hacer la comprobación de un pulsador es tan fácil como poner:

bucle        btfss     PORTA,1 ; Comprueba pulsador conectado en RA1.
             goto     bucle

             call       R20MS ; Haz una subrutina y solo tendras que poner esto en el código, sin tener que escribirla tu cada dos por tres.

             btfss     PORTA,1; Comprueba de nuevo, eliminando los rebotes
             goto      bucle

             TU CODIGO -> Y aqui sigues con tu codigo.




En breves te pongo otro enlace con un ejemplo de una subrutina
El final del camino no está determinado, lo determinamos nosotros mismos paso a paso, día a día, y se puede cambiar.

Fox_Neo

Gracias Firos por responder siempre me gustan tus respuestas y aprendo bastante. A ver si lo he entendido, te refieres que se compruebe el estado de la entrada cada cierto tiempo ¿no?

Firos

Cita de: Fox_Neo en 29 Marzo 2013, 00:20 AM
Gracias Firos por responder siempre me gustan tus respuestas y aprendo bastante. A ver si lo he entendido, te refieres que se compruebe el estado de la entrada cada cierto tiempo ¿no?


No...

Mira esta imagen:


Bien, en la parte de arriba, vemos una señal que va desde 0 a 5 V pero... al ser un interruptor mecánico, el contacto que hacen los dos bornes metálicos para dejar pasar la corriente no es perfecto y rebota un poco, dando ese efecto que aparece en la parte de arriba a la izquierda de la imagen, una señal que hace "ziczac".

Esos rebotes no los percibimos porque transcurren en microsegundos. El problema es que los microprocesadores trabajan mucho más rápido. Por ejemplo, un microprocesador trabajando a 4Mhz realiza una instrucción en cada microsegundo.

Eso que ves a la derecha es una forma de eliminar esos rebotes sin usar ningun programa, haciéndolo mediante Hardware pero eso no nos interesa aquí (aunque no está mal saberlo). Como ves, la señal de la derecha va desde "0" lógico a "1" lógico sin ningún problema.


Ahora bien, ¿como eliminamos esto mediante un programa? Con el código que te he puesto.

Tendríamos que comprobarlo un par de veces en un tiempo mínimo, mayor que el de los rebotes y menor de el que una persona pudiera cerrar y abrir el interruptor.

Por esto mismo puedes hacer un retardo de 20 milisegundos (20000 microsegundos) para que no tenga interferencias e implementarlo en el código.


Lo que se suele hacer cuando programamos para simplificar el código son "subrutinas" o "funciones" que son partes de código que se repiten y que con ponerlas una vez en una parte de el código y llamarlas desde donde las queremos ejecutar nos basta.

Por ejemplo: Si el PIC lo tenemos trabajando a 4Mhz con lo que tenemos 1 instrucción por segundo, podemos usar un par de contadores para tal efecto (sin usar los TIMERS para no mantenerlos ocupados y poder usarlos para hacer retardos de otro tipo como PWM, capturas de señal, retardos de tiempo para encender y apagar LEDS, etc, etc).

Imagina que tenemos 2 contadores. Con uno, podemos contar hasta 256, ¿verdad? Y como tenemos trabajando el microprocesador a 4Mhz sabemos que cada vez que ejecutemos una instrucción para incrementarlo (como INCF) tardaremos 1uS (microsegundo).

¿Y si usamos otro contador? Podríamos contar 256 veces el otro contador. Por lo tanto:
256 * 256 = 65536

Podríamos contar trabajando a 4Mhz con dos contadores hasta 65536 uS (65536 milisegundos). Pues bien, ahora solo nos hace falta despejar la formula.

XXX * 200 = 20000  <- Pongo 200 por poner algo, también podríamos ponerle 256 y solo tendríamos que borrar el contador con "CLRF" para que empiece a contar.

20000 / 200 = 100   <- Pues ya sabemos lo que tenemos que cargar en cada contador.


Esto es una manera rápida y cutre de hacerlo. Lo que tendríamos que hacer es un diagrama de flujo (un esquema) con los pasos que hacemos en el contador y sumarle los pasos que tarda en cada acción en cada bucle porque con estos cálculos que te he puesto para que lo entendamos todos en realidad va a tardar bastante mas de 20000 uS (aunque no lo percibirá el ojo humano y podríamos despreciarlo si la finalidad es únicamente comprobar el interruptor).



Esta es la que uso yo, que tiene un desfase de 1uS (que 1/20000 es un fallo mínimo):

;********************************************************************
; "R20MS"
;tsubrutina R20MS = (4.RET1.RET2 + 4.RET2 + 1) micseg.
;Rutina de temporización 20 milisegundos.
;********************************************************************

R20MS movlw .25 ;Carga RET2.
movwf RET2 ; "

R20MS1: movlw .199 ;Carga RET1.
movwf RET1 ; "

R20MS2: clrwdt ;Inicializa WDT.
decfsz RET1,F ;Decrementa RET1 hasta cero.
goto R20MS2 ;Si RET1 no es cero repite decremento.
decfsz RET2,F ;Si RET1=0 decrementa RET2.
goto R20MS1 ;Si RET2 no es 0 repite el bucle.
return



Y la tengo metida dentro de un fichero al que llamo "retardos.inc". Los contadores están en las posiciones altas 0x63, por ahí, para que si programo no me equivoque y ponga otro registro en el mismo sitio.


Luego, en el programa principal, en la parte de abajo ponemos:
include "retardos.inc"

end


Y con eso nos incluirá al compilar el programa la subrutina en nuestro programa. Ahora, desde cualquier otra parte de el programa podemos llamarla con:
call R20MS


Con lo que si miras el programa del POST anterior lo podrás ver mejor:
Cita de: Firos en 26 Marzo 2013, 21:32 PM
Si ya has conseguido que funcione ahora podrías perfeccionarlo.


Cuando comprobamos si un interruptor está a "1" o a "0" hay que eliminar rebotes.

Es decir, cualquier modo de contacto piezoeléctrico al hacer que conecten sus dos "bornes" hay ahí un "ruido" que en ocasiones puede ser que realmente el interruptor no esté a "1" o que en cuanto le des el contador automáticamente se detenga (en caso de que cuando detecte cero se pare).


Por esto mismo te recomiendo que hagas una cosa. Hazte una subrutina de retardos, como la que tienes de 0,5 segundos en este mismo hilo pero con muchas otras de 20 milisegundos, 50 milisegundos, 100 milisegundos, etc, etc.

Para hacer la comprobación de un pulsador es tan fácil como poner:

bucle        btfss     PORTA,1 ; Comprueba pulsador conectado en RA1.
             goto     bucle

             call       R20MS ; Haz una subrutina y solo tendras que poner esto en el código, sin tener que escribirla tu cada dos por tres.

             btfss     PORTA,1; Comprueba de nuevo, eliminando los rebotes
             goto      bucle

             TU CODIGO -> Y aqui sigues con tu codigo.




En breves te pongo otro enlace con un ejemplo de una subrutina


Espero que haya quedado claro :)

Un saludo.
El final del camino no está determinado, lo determinamos nosotros mismos paso a paso, día a día, y se puede cambiar.