Interrupciones PIC

Me llamo Rafa, aunque me puedes llamar File. Me está costando mucho
encontrar alguien que me responda a esta pregunta. He hecho una rutina de
interrupciones, para el PIC16F84, muy simple, para encender un LED cuando
presiono un pulsador y los pasos que he dado son los siguientes: Activo el bit de
flanco para que sea el nivel ascendente el que active la interrupción externa por
RB0, es decir el bit INTDEG del registro OPTION puesto a 1, eso en el banco 1,
luego en el banco 0 activo GIE, INTE del registro INTCON y pongo a 0 el bit INTF,
también de INTCON. A continuación entro en un bucle sin fin que espera a que se
produzca el cierre del pulsador, para que se active la interrupción que, cuando se
activa, se ejecuta el salto a la rutina de encendido del LED, desde el vector de
interrupción, la cual enciende el LED para, a continuación, hacer una pausa. Bien, el
problema es que no retorna de esa pausa para seguir con la rutina de encendido
que, apagaría el LED efectuaría otra pausa, pondría a 0 el señalizador de
interrupción INTF y retornaría con RETFIE al bucle sin fin, para volver
a empezar de nuevo. ¿Puede ser que el PIC tarde en poner GIE a nivel 0 lo
suficiente para que los rebotes eléctricos del pulsador provoquen varias
interrupciones, por lo que esta situación llenaría la pila, de direcciones de retorno
(Una por cada interrupción, ya sabes), ¿impidiendo el almacenamiento de la
dirección de retorno de una nueva llamada? Si no es así, entonces ¿qué esta
pasando en mi programa?

2 Respuestas

Respuesta
1
Para probar si tu problema es con rebores, tendrías que desactivar las interrupciones hasta que finalices con tu rutina de encendido y apagado del led, para eso la primer linea de la rutina de encendido que es la que figura en el vector de interrupción, tendría que ser
Bcf intcon, gie
Luego, al finalizar tu rutina, simplemente poniendo RETFIE se restablece la captura de interrupciones, el llenado de la pila no seria problem, porque siempre la ultima dirección es la de retorno a la rutina sin fin, perderías las direcciones más viejas, pero a vos te sirve solo la ultima, tienes solo un retfie.
Si el problema no es este, enviame tu rutin de tiempos, en algún lado debe estar el problema.
Si se soluciono el problema, finaliza la pregunta avisándome, sino respóndeme y seguimos intentando.
Hola otra vez
GIE lo pone el microcontrolador a cero automáticamente, no hace falta tenerlo en cuenta en la rutina. Me han respondido del laboratorio de ayuda de la colección que adquirí para montar un pequeño robot (Monty) y me han dicho que lo de los rebotes no es el problema, ya que el micro pone GIE a cero en un tiempo menor del que tarda en aparecer el primer rebote. Comparto lo del retorno a pesar de la pila llena, pero, en ese caso, seguiría sin apagar el LED, ya que seguiría retornando antes de llegar a esa parte (en la primera llamada a pausa). Te envío la rutina, es muy simple, no te será pesado el análisis :). Gracias.
list p=16f84
include "P16f84a.INC"
CONT1 EQU 0x0c
CONT2 EQU 0x0d
CONT3 EQU 0x0e
CONT4 EQU 0x0f
SPEED EQU 0x11
org 0
goto Inicio
org 4
goto LEE_CHOQUE
Inicio bsf STATUS,RP0 ; Banco 1
movlw b'00011110'
movwf PORTA
movlw b'00001111'
movwf PORTB
bsf OPTION_REG,INTEDG ; Pone a 1 INTDEG, para que sea el flanco
; ascendente el que active la interr. en RB0
bcf STATUS,RP0 ; Banco 0
bsf INTCON,GIE ; Activa GIE (permiso global de interr.) y
bsf INTCON,INTE ; INTE (permiso particular de interr.) para RB0.
bcf INTCON,INTF ; Aseguramos reset del señalizador de interrup.
PRINC: goto PRINC
; ***** RUTINA DE LA INTERRUPCIÓN *****
LEE_CHOQUE: movlw b'00000001' ; Enciende LED
movwf PORTA
movlw 0x0a ; Define el tiempo
movwf SPEED ; De la pausa
call PAUSA
movlw b'00000000' ; Apaga LED
movwf PORTA
movlw 0x0a ; Define el tiempo
movwf SPEED ; De la pausa
call PAUSA
bcf INTCON,INTF ; Aseguramos reset del señalizador de interrup.
retfie ; Retorna poniendo GIE a 1 pa activar INT globales
; ***** TRES BUCLES ENLAZADOS PARA LA PAUSA *****
PAUSA: movlw 0x0a
movwf CONT1
movlw 0x0a
movwf CONT2
LAZO1: decfsz CONT1,1
goto LAZO1
decfsz CONT2,1
goto LAZO1
decfsz SPEED,1
goto LAZO1
ret
END
La código esta bien, solo le encuentro que al final de la rutina de pausa utilizas como instrucción la palabra RET, no se que compilador utilizas, pero no es un comando reconocido, el comando correcto es RETURN, te lo debe estar tomando como un label, yo lo estoy emulando y ese es un error grave.
También probé el tema del rebote, y encontró que a lo sumo lo que te puede hacer es que te queda en la cola de interrupciones el rebote del botón, por lo que podes llegar a ver dos destello del LED, para eso desactivarías la interrupción de PORTB hasta salir de la rutina.
Comentame que paso con lo del RET, creo que es ese el problema.
Tío, eres un monstruo je je, ya puedo concluir el programa para mi primer prototipo de robot de unos 670g. De peso. Con esta prueba queda testeado todo el hardware. Es que en spectrum (no se si recuerdas juegos como survivor), incluso en PC siempre use ret como mnemonico en ensamblador. Gracias.
Respuesta
1
¿Me podrías dar el código de ese programa? Es que por lo que dices está bien, pero el problema puede venir de otro lado.
Si quieres me lo puedes mandar a mi e-mail:
[email protected]

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas