Hola!
Estoy empezando a programar microcontroladores y me he quedado en un punto en el que no se avanzar.
Mi programa tiene que tener 3 modos de funcionamiento , (en cada uno de ellos el display mostrará una cosa) , y dentro de cada modo, se podrá elegir entre mostrarlo en el display en sentido ascendente o descendente.
Para pasar de un modo de funcionamiento a otro, se tendrá que detectar una pulsación larga
Para pasar de modo ascendente a descendente o viceversa dentro de un mismo modo se tendrá que realizar una pulsación corta
Tengo habilitadas las interrupciones en el timer y son cada 20 mS. La rutina empieza en T1_INT
Cada vez que vuelva de la interrupción compruebo en qué modo está,si no se pulsaestá pulsado el pulsador, debe mostrar un 2 en un display de 7 segmentos, (eso lo hace bien).
Cuando vuelvo de la interrupción y el pulsador está pulsado, decremento una variable (pulsacionLarga) inicializada a 33h y así 33h*20mS me darán 1200 mS que es lo que considero como pulsación larga, y una variable pulsado a 1. cuando pulsacionLarga esta variable llegue a 0, deberia mostrar el numero 6, ir de nuevo al fin del tratamiento de la rutina (END_ISR) y al programa principal que es un bucle a si mismo.
Cuando vuelva a la interrupcion y ya no esté pulsado el pulsador, si antes había estado pulsado (lo se por la variable pulsado) deberia ir a mostrar3.
El problema es que siempre entra por donde muestra 6 y luego va a mostrar 3, sin importar cuanto vale pulsacionLarga o si ha llegado a 0es decir entra por los dos sitios seguidos, he intentado hacer un debug pero parece que en el debug funciona...
Si me pueden ayudar se lo agradecería mucho
Este es el código:
list p=16f877 ; Indicamos procesador destino y radix
#include P16F877A.INC ; Define gran cantidad de constantes relacionadas con este procesador
__CONFIG _DEBUG_OFF & _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _HS_OSC & _WRT_OFF & _LVP_OFF & _CPD_OFF
#define TICKS 13h ; Ticks entre parpadeo cada tick = 20 mS. = 0,4 segundos cada cambio
tiempoNoMostrar EQU 0x20
display EQU 0x21
tiempoMostrar EQU 0X22
Tiempo EQU 0X23
pulsado EQU 0X24
modo EQU 0X25
cambioModo EQU 0X26
pulsacionLarga EQU 0X27
tarara EQU 0X28
;*********************** INICIO DE LA DEFINICION DE VARIABLES ***********************
w_temp EQU 0x71 ; variable usada pora salvar el contexto
status_temp EQU 0x72 ; variable usada pora salvar el contexto
;************************* FIN DE LA DEFINICION DE VARIABLES ************************
ORG 0x00 ; lo que hay después de esta línea, quedará en la declaración 0 de mi programa
nop ; Este byte está reservado para el ICD
clrf PCLATH ; resetea solo la parte baja cuando hay un reset, no todo el PC counter.
; así garantizo que mi PC está en la parte baja a 0 cuando se resetee, en cualquier caso.
goto Inicio ; las interrupciónes de después se antenderían en la instrucción 4.
;|------------------------------------------------------------------------------|
;|-------------Inicio de las rutinas de atención a interrupción-----------------|
ORG 0x04 ; dirección del vector de interrupción
movwf w_temp ; Salvar el contenido de W
movf STATUS,w ; Salvar el contenido de STATUS
movwf status_temp ; Salvar el contenido de STATUS
goto T1_INT ; SI, atender interrupción.T1
END_ISR
;--------------------- CADA 20 MILISEGUNDOS ME SALTA LA INTERRUPCIÓN DE DESBORDAMIENTO DEL TIMER0 -----------------
movlw 0B2h ; 256-178= 78 pulsos en Timer0 para desbordarse
; 78 pulsos * 256 microSeg. por pulso = 20 mS. aprox.
movwf TMR0 ; t_tic = 20 mseg
;--------------------- CADA 20 MILISEGUNDOS ME SALTA LA INTERRUPCIÓN DE DESBORDAMIENTO DEL TIMER0 -----------------
retfie
T1_INT ; Rutina para la interrupción de Timer1 overflow
;COMPROBAR EN QUE MODO ESTOY
movlw 000h
xorwf modo,0
btfsc STATUS,2
goto TratamientoModo1
movlw 001h
xorwf modo,0
btfsc STATUS,2
goto TratamientoModo2
movlw 002h
xorwf modo,0
btfsc STATUS,2
goto TratamientoModo3
movlw 003h
xorwf modo,0
btfsc STATUS,2
goto TratamientoModo4
goto TratamientoModo5
TratamientoModo1
bcf PIR1,T0IF; Poner a 0 el flag de la interrupción del Timer0
btfsc PORTB,RB0
goto Ver1;no pulsado
bsf PORTB,1;PULSADO
movlw 01h
movwf pulsado
decf pulsacionLarga,1
movlw 00h
xorwf pulsacionLarga,0
btfss STATUS,2
goto END_ISR;si no ha llegado a pulsacion larga
goto CambiarModo3
Ver1;no pulsado
movlw 01h;si NO ha estado pulsado antes tengo que mostrar
xorwf pulsado,0
btfss STATUS,2
goto Mostrar;no activado con anterioridad
bcf PORTB,1;activado con anterioridad
goto CambiarSentido2 ;no es cambiar de modo
CambiarSentido2
movlw 03h
call hex27seg
movwf PORTC
call Pausa
goto END_ISR
CambiarModo3
movlw 00h
xorwf pulsacionLarga,0
btfss STATUS,2
goto END_ISR
movlw 06h
call hex27seg
movwf PORTC
goto END_ISR
TratamientoModo2
goto END_ISR
TratamientoModo3
goto END_ISR
TratamientoModo4
goto END_ISR
TratamientoModo5
goto END_ISR
Mostrar
movlw 02h
call hex27seg
movwf PORTC
call Pausa
goto END_ISR ; Fin de la rutina
Inicio
banksel TRISB ; Seleccionamos el Banco1
; TRISA, TRISB, etc. (están en el banco 1: por defecto estoy en el banco 0, por haber arrancado)
; Configuración puertos: usaremos 2 elem de salida: led(pin 1 del puerto b) y dilplay(8 pines del puerto c)
movlw B'00000001' ;llevar al registro de trabajo ese valor
movwf TRISB ; Bit 0 de PORTB entrada, el resto como salida (1 es entrada, 0 es salida)
clrf TRISC ; PORTC configurado como salidas en todos sus bits
; Configuración del timer
movlw b'01010111'
movwf OPTION_REG
banksel PORTB ; Seleccionamos el Banco0, pues como option reg está en todos los campos, no pasa nada, pero me debo mover a portb para después.
clrf PORTB
;////////////////////// Habilitar interrupciones //////////////////////
banksel PORTB ; banco 0
bsf INTCON,PEIE ; Habilito interrupciones de perifericos
bsf INTCON,GIE ; Habilito interrupciones globales
banksel TRISB ; banco 1
bsf INTCON,T0IE ; Habilitamos interrupcion overflow del timer 0
banksel PORTB ; banco 0
bcf INTCON,T0IF ; Limpio flag interrupción
;////////////////////// Habilitar interrupciones //////////////////////
;--------------------- CADA 20 MILISEGUNDOS ME SALTA LA INTERRUPCIÓN DE DESBORDAMIENTO DEL TIMER0 -----------------
movlw 0B2h ; 256-178= 78 pulsos en Timer0 para desbordarse
; 78 pulsos * 256 microSeg. por pulso = 20 mS. aprox.
movwf TMR0 ; t_tic = 20 mseg
;--------------------- CADA 20 MILISEGUNDOS ME SALTA LA INTERRUPCIÓN DE DESBORDAMIENTO DEL TIMER0 -----------------
movlw 00h
movwf pulsado
movlw 00h
movwf modo
movlw 30h
movwf pulsacionLarga
movlw 00h
movwf cambioModo
Bucle
goto Bucle
Pausa
movlw TICKS ; tiempo_espera = TICKs * t_tic
movwf Tiempo ; guarda valor en memoria
Otro_tic
movlw 0B2h ; 256-178= 78 pulsos en Timer0 para desbordarse
; 78 pulsos * 256 microSeg. por pulso = 20 mS. aprox.
movwf TMR0 ; t_tic = 20 mseg
Sigue
btfss INTCON,T0IF ; ¿desbordamiento?
goto Sigue ; no
bcf INTCON,T0IF ; si -> repongo flag
decfsz Tiempo, F ;se repite el
goto Otro_tic
return
;****************************************
hex27seg
;****************************************
; Subrutina hex27seg, que recibe un valor hexadecimal de un dígito en W,
; y devuelve en el mismo registro el valor correspondiente al de un
; display de 7 segmentos.
; A continuación se muestra el nombre de cada segmento en un Display
;
;* RC0/RC7 Display de 7 segmentos
;* -----
;* | a |
;* f| |b
;* | |
;* -----
;* | g |
;* e| |c
;* | |
;* -----
;/ d .dp
;* RC0 dp
;* RC1 segmento c
;* RC2 segmento d
;* RC3 segmento e
;* RC4 segmento g
;* RC5 segmento f
;* RC6 segmento a
;* RC7 segmento b
;
andlw b'0001111' ; Nos aseguramos que está en el rango 0..15
addwf PCL, F ; se desplaza el PCL (funciona como un switch)
retlw b'11101110' ; se muestra 0
retlw b'10000010' ; se muestra 1
retlw b'11011100' ; se muestra 2
retlw b'11010110' ; se muestra 3
retlw b'10110010' ; se muestra 4
retlw b'01110110' ; se muestra 5
retlw b'01111110' ; se muestra 6
retlw b'11000010' ; se muestra 7
retlw b'11111110' ; se muestra 8
retlw b'11110010' ; se muestra 9
retlw b'11111011' ; se muestra A
retlw b'00111111' ; se muestra B
retlw b'01101101' ; se muestra C
retlw b'10011111' ; se muestra D
retlw b'01111101' ; se muestra E
retlw b'01111001' ; se muestra F
END