Si entendi correctamente:
Al soltarse RB0: Debe parpadear 3 veces.
Si se presiona y suelta RB0 finalizado el parpadeo, no debe pasar nada.
Si se presiona y suelta RB0 mientra parpadea, no debe pasar nada.
Si se presiona RB1 luego de lo anterior, debe habilitar a RB0 a hacer otros 3 parpadeos
Si se presiona RB1 mientras hace los parpadeos: ??????? voy a suponer que debe terminar los parpadeos
Si se presiona RB1 antes de que RB0 haga algo, entonces no pasa nada.
me voy a basar en lo que entendi.
Bueno te explico masomenos como va el tema de las interrupciones:
- Nunca podes tener un loop que no salga (o tener un boton como RB1 con ese goto ) dentro de la interrupcion. Si haces eso, entonces no tiene tener una interrupcion. Ya que estarias bloqueando las otras posibles interrupciones ( en caso que tengas varias) tal ves aca no te afecte, pero en si mejor acostumbrarse a eso.
- Te falta el guardar el contexto y restablecerlo al salir , con contexto me refiero a los registros STATUS, W y PCLATH, ya que si vuelve al programa principal luego de que vos cambiaste los valores de W y STATUS (valores que trabajste en la interrupcion ) no van a ser los mismos que venia usando el programa principal. Microchip ofrece el codigo, busca W_TEMP en el datasheet y lo vas a encontrar.
Esto que nombre te va a llevar a tener un solo RETFIE.
Respecto al programa, no se si vale la pena usar la interrupcion para este ejemplo, pero creo que estas intentando hacerlo asi. Asi que vamos a seguir con esa idea.
Primero vamos a la base:
list p=16f886
#include <p16f886.inc>
__CONFIG _CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
__CONFIG _CONFIG2, _WRT_OFF & _BOR21V
CBLOCK 0x70
W_TEMP ; 0x70
STATUS_TEMP ; 0x71
ENDC
ORG 0x000
GOTO INICIO
ORG 0X004
GOTO INTERRUPCION
INICIO
;Configuracion de puertos/modulos
; Inicializacion de cualquier variable
LOOP
; Loop principal
GOTO LOOP
INTERRUPCION
; Guardo
MOVWF W_TEMP
SWAPF STATUS,W
MOVWF STATUS_TEMP
; Comienza codigo de interrupcion
BTFSC INTCON, INTF
CALL INT_BOTON_RB0
; Fin de codigo de interrupcion
; Reestablezco
SWAPF STATUS_TEMP,W
MOVWF STATUS
SWAPF W_TEMP,F
SWAPF W_TEMP,W
RETFIE
END
De aca debemos pensar el programa
La seccion de configuracion me parece correcta. Por lo que no deberia tocarse. Pero lo demas hay que pasarle una repasada.
En la interrupcion tenemos 2 casos a tener en cuenta:
- Cuando se presiona ( supongamos que va a 0V al presionarlo ) entonces es cuadno se detecta un flanco descendente. Este no nos interesa para nada.
- Cuando se suelta, si seguimos con el la idea, entonces al soltarlo tenemos un flanco ascendente. Este si nos interesa. Asi que estaria bien configurado.
Una ves detectado el boton, podriamos usar un bit de algun registro para saber si tenemos permitido hacer o no los parpadeos.
Vamos a crear un registro llamado BANDERAS el cual el bit 0 va a indicar si debe hacerse o no los parpadeos.
La interrupcion es simple... Es activar este bit y desactivar la interrupcion de RB0
INT_BOTON_RB0
BCF INTCON, INTF
BTFSC BANDERAS, 0
GOTO ACTIVO_TODAVIA ;Por si se quiere agregar algun codigo que haga algo si es que se suelta mientras esta parpadeando
BSF BANDERAS, 0 ; Activo el bit para saber que ya puede parpadear
BCF INTCON, INTE ; Desactivo las interrupciones de RB0
MOVLW 0x06
MOVWF CONTADOR ; Recargo el contador de parpadeos
ACTIVO_TODAVIA
RETURN
Por otra parte necesitamos hacer el Loop principal, en este loop vamos a leer RB1 y actuar en consecuencia, y ademas hacer el parpadeo.
LOOP
CALL LEER_RB1
CALL LED_TMR
GOTO LOOP
Respecto a RB1:
Si estan desactivadas las interrupciones de RB0 esto nos dice que ya se presiono antes RB1, por lo que no nos interesa hacer nada en ese caso. Luego observamos si esta presionado RB1, si lo esta, procedemos a reactivar las interrupciones.
LEER_RB1
BTFSS INTCON, INTE
RETURN ; En caso que no este activado las interrupciones ( se presione 2 veces RB1)
BTFSS PORTB, 1 ; Se presiono RB1
RETURN
BCF INTCON, INTF ; Limpio bandera
BSF INTCON, INTE ; Activo nuevamente las interrupciones.
RETURN
Respecto al parpadeo:
Aca dijimos que ibamos a usar el bit 0 de BANDERAS para saber si debiamos parpadear o no. Por eso mismo lo primero que leemos es si este bit nos habilita o no a parpadear.
De alli si esta habilitado necesitamos saber si paso o no el tiempo de parpadeo, si no paso que salga y pruebe leer RB1 y que vuelva.
Si se cumplio el tiempo, cambiamos el estado de RC0, recargamos el Timer, y borramos la bandera del Timer, ademas tenemos que llevar la cuenta de cuantas veces cambiamos la salida, por eso usamos otro registro llamado CONTADOR.
Mientras no se termina de parpadear, esto sigue, cuando se termina, pone a 0 el bit de BANDERAS, para indicar que termino y no debe entrar mas. Y la unica forma que se habilite es que se presione RB1 (para activar las interrupciones) y que luego se presione/suelte RB0 para activar nuevamente este bit.
LED_TMR
BTFSS BANDERAS, 0 ; Tengo que parpadear ?
RETURN
BTFSS INTCON, T0IF ; Paso el tiempo?
RETURN ; No paso el tiempo, vuelvo
MOVLW 0x01
XORWF PORTC ; Invierto el estado de RC0
MOVLW .12
MOVWF TMR0 ; Recargo el timer
BCF INTCON, T0IF ; Limpio bandera
DECFSZ CONTADOR, F ; Decremetno la cantidad de parpadeos
RETURN
;Aca llegamos cuando se termino contador
BCF BANDERAS, 0 ; Se terminaron los 3 parpadeos, entonces procedo a apagar la funcion de parpadeo
RETURN