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:
Con lo que si miras el programa del POST anterior lo podrás ver mejor:
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.