__CONFIG _CP_OFF& _WDT_ON&_PWRTE_OFF&_BODEN_OFF&_INTRC_OSC_NOCLKOUT&_MCLRE_OFF
LIST P=12F629
#INCLUDE <P12F629.INC>
ERRORLEVEL -302
CBLOCK 0x20 ; ponemos 0x20 para que valga para todos
; incluido 12f629
CONTADOR
CONTADOR_1
REG_1
PDel0
PDel1
PDel2
PDel3
ENDC
#DEFINE LED_I GPIO,1
#DEFINE LED_D GPIO,0
#DEFINE PUL_I GPIO,4
#DEFINE PUL_D GPIO,5
ORG h'0000' ; VECTOR DE RESET
goto INICIO ; va a inicio
ORG h'0004' ; VECTOR DE INTERRUPCIONES
INICIO
clrf GPIO
movlw 07h
movwf CMCON ; todos los pines en modo digital.
bsf STATUS,5 ; activa la página 1
movlw b'111100' ; GP0 y 1 salidas 2, 3, 4 y 5 entradas.
movwf TRISIO
call CALIBRAOSC
movwf OSCCAL
clrf INTCON ; deshabilitar interrupciones.
movlw 0X07 ; TIMER con prescaler de 256, para 50ms
movwf OPTION_REG
movlw 0X20 ; habilitamos desborde de TIMER pero sin interrupción
movwf INTCON ; cada 50ms nos seteara el flag TOIF de INTCON
bcf STATUS,5 ; volvemos a la página 0
clrf GP0 ; apagamos led D
clrf GP1 ; y el led I
clrf CONTADOR
clrf CONTADOR_1
clrf REG_1
ESPERA
btfss PUL_I
goto $+3 ; va tres posiciones para adelante
call ANTIRREBOTES
goto MAIN
btfss PUL_D
goto ESPERA
call ANTIRREBOTES
goto MAIN
TABLA ; esta tabla nos dirá que hay que hacer
addwf PCL,1
goto ESPERA ; aquí nunca vendrá, pero por si acaso....
goto DERECHA
goto IZQUIERDA
goto LOS_DOS
MAIN
btfss PUL_D ; miramos si en PUL_D hay un 1 o un 0
bcf REG_1,0 ; y escribimos en un registro lo que haya
btfsc PUL_D ; en el bit 0
bsf REG_1,0
btfss PUL_I ; hacemos lo mismo con el otro pulsador
bcf REG_1,1 ; éste lo escribimos en el bit 1
btfsc PUL_I
bsf REG_1,1 ; aquí ya tenemos los dos pulsadores leidos y anotados en un registro
movf REG_1,0 ; lo movemos a W
call TABLA
goto ESPERA
CAMBIA_I ; esta rutina se ejecutará solo cuando cambie de un intermitente al otro
; y hará un antirrebotes de 20ms para asegurarse de que no fue un rebote
bcf LED_D
call ANTIRREBOTES_1
btfss PUL_I ; comprueba que realmente se pulsó
goto ENCIENDE_D ; falsa alarma va a donde estaba
btfsc PUL_I ; se espera hasta que se suelte
goto $-1
call ANTIRREBOTES_1 ; llama antirrebotes para confirmar
btfsc PUL_I ; se mira si de verdad se soltó
return ; pasó algo raro vuelve a MAIN
btfsc PUL_D ; y que el otro botón esta desactivado
return ; se pulsaron los dos va a main a iniciar secuencia
bcf INTCON,2
clrf CONTADOR
clrf CONTADOR_1
goto ENCIENDE_I
IZQUIERDA
btfsc PUL_I ; Aquí espera hasta que se suelte pulsador
goto $-1 ; va una posición para atrás
call ANTIRREBOTES_1 ; para comprobar si hay rebotes al soltar
btfsc PUL_I ; se confirma que se soltó pulsador
return ; falsa alarma va a MAIN
bcf INTCON,2 ; se soltó y no hay rebotes
clrf CONTADOR ; pone contadores a 0 e inicia secuencia
clrf CONTADOR_1
goto ENCIENDE_I
DESACTIVAR_I
bcf LED_I
clrf CONTADOR
clrf CONTADOR_1
btfsc PUL_I ; espera hasta que se suelte pulsador
goto $-1 ; porque si retornara sin esperar volvería a secuencia
call ANTIRREBOTES_1
btfsc PUL_I ; después de antirrebotes confirma se soltó
goto $-4 ; fueron rebotes va a primer chequeo
return ; apaga flag e intermitente y vuelve a MAIN, FLAG estaba a 1
ENCIENDE_I
bsf LED_I ; enciende intermitente izquierda
movlw .61 ; cargamos TIMER0 con 61 para que nos cuente 50ms
movwf TMR0 ; porque si empezara de 0 contaría 65536
btfsc PUL_D
goto CAMBIA_D ; si mientras esta ejecutando una secuencia
; se pulsa un botón empieza de nuevo
btfsc PUL_I
goto DESACTIVAR_I
btfss INTCON,2 ; pasaron 50ms? se desbordó TIMER?
goto $-5 ; no seguimos esperando y chequeando pulsadores
bcf INTCON,2 ; se desbordó, borramos flag para la próxima vez
incf CONTADOR_1,1
movlw .1 ; número de veces que se repite el retardo de 50ms
subwf CONTADOR_1,0 ; modificando este número aumentará o reducirá en 50ms el tiempo
btfss STATUS,Z
goto ENCIENDE_I
clrf CONTADOR_1 ; ponemos a 0 contador
APAGA_I
bcf LED_I ; apaga
movlw .61 ; cargamos TIMER0 con 61 para que nos cuente 50ms
movwf TMR0 ; porque si empezara de 0 contaría 65536
btfsc PUL_D
goto CAMBIA_D ; si mientras esta ejecutando una secuencia
; se pulsa un botón empieza de nuevo
btfsc PUL_I
goto DESACTIVAR_I
btfss INTCON,2 ; pasaron 50ms? se desbordó TIMER?
goto $-5 ; no seguimos esperando y chequeando pulsadores
bcf INTCON,2 ; se desbordó, borramos flag para la próxima vez
incf CONTADOR_1,1
movlw .20 ; número de veces que se repite el retardo de 50ms
subwf CONTADOR_1,0 ; modificando este número aumentará o reducirá en 50ms el tiempo
btfss STATUS,Z
goto APAGA_I
clrf CONTADOR_1 ; ponemos a 0 contador
incf CONTADOR,1 ; para número de veces que encenderá
movlw .10 ; le pongo 10 pero pueden ser las que tu quieras
subwf CONTADOR,0
btfss STATUS,Z ; van 10 veces?
goto ENCIENDE_I ; no, vuelve a repetir secuencia
clrf CONTADOR
goto DESACTIVAR_I
CAMBIA_D ; esta rutina se ejecutará solo cuando cambie de un intermitente al otro
; y hará un antirrebotes de 20ms para asegurarse de que no fue un rebote
bcf LED_I ;
call ANTIRREBOTES_1
btfss PUL_D ; comprueba que realmente se pulsó
goto ENCIENDE_I ; falsa alarma va a donde estaba
btfsc PUL_D ; se espera hasta que se suelte
goto $-1
call ANTIRREBOTES_1 ; llama antirrebotes para confirmar
btfsc PUL_D ; se mira si de verdad se soltó
return ; pasó algo raro vuelve a MAIN
btfsc PUL_I ; y que el otro botón esta desactivado
return ; se pulsaron los dos va a main a iniciar secuencia
bcf INTCON,2
clrf CONTADOR
clrf CONTADOR_1
goto ENCIENDE_D
DERECHA
btfsc PUL_D ; Aquí espera hasta que se suelte pulsador
goto $-1 ; va una posición para atrás
call ANTIRREBOTES_1 ; para comprobar si hay rebotes al soltar
btfsc PUL_D ; se confirma que se soltó pulsador
return ; falsa alarma va a MAIN
bcf INTCON,2
clrf CONTADOR
clrf CONTADOR_1
goto ENCIENDE_D
DESACTIVAR_D
bcf LED_D
clrf CONTADOR
clrf CONTADOR_1
btfsc PUL_D ; espera hasta que se suelte pulsador
goto $-1 ; porque si retornara sin esperar volvería a secuencia
call ANTIRREBOTES_1
btfsc PUL_D ; después de antirrebotes confirma se soltó
goto $-4 ; fueron rebotes va a primer chequeo
return ; apaga intermitente y vuelve a MAIN
ENCIENDE_D
bsf LED_D ; enciende intermitente
movlw .61 ; cargamos TIMER0 con 61 para que nos cuente 50ms
movwf TMR0 ; porque si empezara de 0 contaría 65536
btfsc PUL_D
goto DESACTIVAR_D ; si mientras esta ejecutando una secuencia
; se pulsa un botón empieza de nuevo
btfsc PUL_I
goto CAMBIA_I
btfss INTCON,2 ; pasaron 50ms? se desbordó TIMER?
goto $-5 ; no seguimos esperando y chequeando pulsadores
bcf INTCON,2 ; se desbordó, borramos flag para la próxima vez
incf CONTADOR_1,1
movlw .1 ; número de veces que se repite el retardo de 50ms
subwf CONTADOR_1,0 ; modificando este número aumentará o reducirá en 50ms el tiempo
btfss STATUS,Z
goto ENCIENDE_D
clrf CONTADOR_1 ; ponemos a 0 contador
APAGA_D
bcf LED_D ; apaga
movlw .61 ; cargamos TIMER0 con 61 para que nos cuente 50ms
movwf TMR0 ; porque si empezara de 0 contaría 65536
btfsc PUL_D
goto DESACTIVAR_D ; si mientras esta ejecutando una secuencia
; se pulsa un botón empieza de nuevo
btfsc PUL_I
goto CAMBIA_I
btfss INTCON,2 ; pasaron 50ms? se desbordó TIMER?
goto $-5 ; no seguimos esperando y chequeando pulsadores
bcf INTCON,2 ; se desbordó, borramos flag para la próxima vez
incf CONTADOR_1,1
movlw .20 ; número de veces que se repite el retardo de 50ms
subwf CONTADOR_1,0 ; modificando este numero aumentará o reducirá en 50ms el tiempo
btfss STATUS,Z
goto APAGA_D
clrf CONTADOR_1 ; ponemos a 0 contador
incf CONTADOR,1 ; para número de veces que encenderá
movlw .10 ; le pongo 10 pero pueden ser las que tu quieras
subwf CONTADOR,0
btfss STATUS,Z ; van 10 veces?
goto ENCIENDE_D ; no, vuelve a repetir secuencia
clrf CONTADOR
goto DESACTIVAR_D
LOS_DOS
btfsc PUL_I
goto $-1
btfsc PUL_D ; miramos si están sin pulsar ambos botones
goto $-3
call ANTIRREBOTES_1
movf GP4,0 ; movemos estado pul I a W
andwf GP5,0 ; y le sumamos el estado del pul D para comprobar que vale 0
btfsc STATUS,Z ; encendió FLAG de 0?
goto LOS_DOS ; fueron rebotes vuelve a comprobar despulsación
clrf CONTADOR
clrf CONTADOR_1
bcf INTCON,2
goto ENCIENDE_LOSDOS
DESACTIVAR_LOSDOS
btfsc PUL_I
goto $-1
btfsc PUL_D ; miramos si están sin pulsar ambos botones
goto $-3 ; para confirmar que se soltaron
call ANTIRREBOTES_1
movf GP4,0
andwf GP5,0
btfsc STATUS,Z ; comprobamos que el valor de GP4 y 5 es 0, no pulsados
goto ENCIENDE_LOSDOS ; no se soltaron, vuelve a encender los dos
clrf GP0 ; apagamos intermitentes
clrf GP1
clrf CONTADOR
clrf CONTADOR_1
return
ENCIENDE_LOSDOS
bcf INTCON,2
bsf GPIO,0 ; encendemos led D
bsf GPIO,1 ; y led I
movlw .61 ; cargamos TIMER0 con 61 para que nos cuente 50ms
movwf TMR0 ; porque si empezara de 0 contaría 65536
btfsc PUL_I
goto DESACTIVAR_LOSDOS ; si mientras esta ejecutando una secuencia
; se pulsa un botón empieza de nuevo
btfsc PUL_D
goto DESACTIVAR_LOSDOS
btfss INTCON,2 ; pasaron 50ms? se desbordó TIMER?
goto $-5 ; no seguimos esperando y chequeando pulsadores
bcf INTCON,2 ; borramos flag para la próxima vez
incf CONTADOR_1,1
movlw .1 ; número de veces que se repite el retardo de 50ms
subwf CONTADOR_1,0 ; modificando este numero aumentará o reducirá en 50ms el tiempo
btfss STATUS,Z
goto ENCIENDE_LOSDOS
clrf CONTADOR_1 ; ponemos a 0 contador
APAGA_LOSDOS
bcf GPIO,0 ; apagamos led D
bcf GPIO,1 ; y led I
movlw .61 ; cargamos TIMER0 con 61 para que nos cuente 50ms
movwf TMR0 ; porque si empezara de 0 contaría 65536
btfsc PUL_I
goto DESACTIVAR_LOSDOS ; si mientras esta ejecutando una secuencia
; se pulsa un botón empieza de nuevo
btfsc PUL_D
goto DESACTIVAR_LOSDOS
btfss INTCON,2 ; pasaron 50ms? se desbordó TIMER?
goto $-5 ; no seguimos esperando y chequeando pulsadores
bcf INTCON,2 ; borramos flag para la próxima vez
incf CONTADOR_1,1
movlw .20 ; número de veces que se repite el retardo de 50ms
subwf CONTADOR_1,0 ; modificando este numero aumentará o reducirá en 50ms el tiempo
btfss STATUS,Z
goto APAGA_LOSDOS
clrf CONTADOR_1 ; ponemos a 0 contador
goto ENCIENDE_LOSDOS
ANTIRREBOTES ;
movlw .110 ; 1 set número de repetición (B)
movwf PDel0 ; 1 |
PLoop1
movlw .181 ; 1 set número de repetición (A)
movwf PDel1 ; 1 |
PLoop2
clrwdt ; 1 clear watchdog
clrwdt ; 1 ciclo delay
decfsz PDel1,1 ; 1 + (1) es el tiempo 0 ? (A)
goto PLoop2 ; 2 no, loop
decfsz PDel0,1 ; 1 + (1) es el tiempo 0 ? (B)
goto PLoop1 ; 2 no, loop
PDelL1
goto PDelL2 ; 2 ciclos delay
PDelL2
goto PDelL3 ; 2 ciclos delay
PDelL3
clrwdt ; 1 ciclo delay
return ; 2+2 Fin.
ANTIRREBOTES_1 ; antirrebotes de 20ms solo cuando esta funcionando uno
; y se cambia para el otro, sin pasar por MAIN
movlw .21 ; 1 set número de repetición (B)
movwf PDel2 ; 1 |
PLoop3
movlw .237 ; 1 set número de repetición (A)
movwf PDel3 ; 1 |
PLoop4
clrwdt ; 1 clear watchdog
decfsz PDel3,1 ; 1 + (1) es el tiempo 0 ? (A)
goto PLoop4 ; 2 no, loop
decfsz PDel2,1 ; 1 + (1) es el tiempo 0 ? (B)
goto PLoop3 ; 2 no, loop
PDelL4
goto PDelL5 ; 2 ciclos delay
PDelL5
clrwdt ; 1 ciclo delay
return ; 2+2 Fin.
org 0x3FF
CALIBRAOSC retlw 0x80 ;calibro oscilador a 4 mhz +- 2%
END