Te explico como funciona la interrupcion..
El microcontrolador al resetearse comienza en la direccion 0x0000 (vector de reset), de allí uno configura los puertos, interrupciones, etc, y como paso final activa las interrupciones.
Luego como todo programa tiene un main, o un loop infinito, el cual va a estar ejecutandose continuamente. Supongamos que tenes este programa y las direcciones que ocupan las instrucciones, voy a intentar simplificarlo:
MAIN:
BSF PORTB,5 ;Direccion de la instruccion 0x100
CALL DELAY ;Direccion de la instruccion 0x101
BCF PORTB,5 ;Direccion de la instruccion 0x102
CALL DELAY ;Direccion de la instruccion 0x103
GOTO MAIN ;Direccion de la instruccion 0x104
Si esta activada la interrupcion al momento de que el micro detecta una, guarda la direccion donde se estaba ejecutando y salta al vector interrupcion. Por ejemplo digamos que estaba en el BCF del programa de arriba (ya lo ejecuto), entonces guarda el 0x103 en un registro interno al micro. Y salta a la direccion 0x0004 que es el vector de reset.
En el momento que llega alla, desactiva las interrupciones, Aca vos vas a tener que revisar cual es la interrupcion que se activo (leyendo los flags) y actuar en consecuencia, una ves finalizada tu rutina limpias la bandera y salis de la interrupcion con un RETFIE, la difernecia entre este y un return es que ademas activa nuevamente las interrupciones. Y devuelve al contador de programas ( PCL ) el valor 0x103. continuando el main desde donde lo dejo..
Como es tan rapido, parece como si estuvieran ejecutandose en "paralelo". Y los podrias considerar casi independientes uno de otro.
Y esta es la esencia de la interrupcion.
Hay otras cosas que tener en cuenta:
- Los registros STATUS y W no se guardan, asi que es necesario guardarlos al comienzo de la interrupcion y luego reponerlos al final de la interrupcion para que el programa principal no cambie en nada.
- Nunca deberias poner delays en una interrupcion, siempre tiene que ser lo mas rapido posible, a no ser que no te importe lo que esta en el main, Ya que como dije mientras estas en la interrupcion las interrupciones estan deshabilitadas! Y si tenes grandes demoras, otras interrupciones se pueden superponer, por ejemplo, podrian llegar 2 caracteres por la UART y debido a que esta trabado en la interrupcion de tu boton, no las atenderia. El programa seria:
org 0x00
goto Inicio
org 0x04
; Aca agregar las instrucciones de guardar W y STATUS
btfss INTCON, INTF ; pregunto si es por el RB0 la interrupcion
goto fin_interrupcion
bcf INTCON, INTF ; limpio el flag de la interrupción
;Aca tu rutina de encender lo que deba encederse o apagar.
fin_interrupcion:
; Aca agregar las instrucciones de volver a su estado original W y STATUS
retfie ; Return especial para las rutinas de interrupción
Inicio
bsf STATUS,RP0 ; me muevo al Banco 1
movlw b'00000001' ; configuro el TRISB: RB0 entrada y el resto salida
movwf TRISB
bcf STATUS, RP0 ; regreso al Banco 0
; Siemrpe al ultimo esto, primer habilito los modulos, limpio la banderas y luego habilito el global
bsf INTCON,INTE ; habilito la interrupción por RB0
bcf INTCON, INTF ; bajo el flag de la interrupción
bsf INTCON,GIE ; habilito las interrupciones globales
main:
goto $ ; Tu loop infinito
end
Q&A que te pueden surgir:- ¿Dónde puedo conseguir el codigo para guardar el W y el STATUS sin que se modifiquen estos?
EN el datasheet del micro busca por W_TEMP y seguramente esta el codigo, algunos hasta guardan el registro PCLATH
- ¿Por que mi profesor no nos dijo de este codigo?
Por que si observas en tu main, o loop principal, no tenes NADA, es decir no vas a cambiar W, no vas a depender del valor de alguna bandera, entonces tiene poca o ninguna importancia usar este codigo, pero es buena practica enseñarselos para que lo tengan en cuenta.
- ¿Por que desactivo las interrupciones y las volvió a habilitar?
Por que no conoce como funciona el nucleo del microcontrolador. Al entrar a la interrupción se desactiva, y si buscas por la instrucción RETFIE en el datasheet, vas a ver que no solo hace como un RETURN sino que ademas pone un 1 en GIE.
- ¿Por que mi profesor no lee con el BTFSS/C si es la flag activada la correcta?
Seguramente por que es el unico modulo que tenes activo la interrupcion, entonces si entra a la interrupcion no queda mas que es esa. Si tuvieras varias harias algo asi:
;Guardo W y STATUS
BTFSC FLAG_INT_1
CALL INT_1_RESPUESTA
BTFSC FLAG_INT_1
CALL INT_1_RESPUESTA
BTFSC FLAG_INT_1
CALL INT_1_RESPUESTA
;Reponer W y STATUS
RETFIE
- ¿Porque limpias las banderas antes de activarlo? Precaucion, ya que las banderas pueden estar en 1, debido a que ocurrio un flanco mientras nosotros estabamos configurando los puertos. Entonces para no tomar como un error un posible flanco en ese momento, limpiamos y comenzamos desde ese punto a escuchar por interrupciones.
- ¿Que pasa si no limpio el flag?
Apenas sale de la interrupcion, al ejecutarse el RETFIE y activar nuevamente la interrupcion global, accede NUEVAMENTE a la interrupcion.
- Al estar desactivadas las interrupciones, ¿Que pasa con interrupciones que ocurran en ese momento?
Lo mismo que antes, los flags van a cambiar a 1, pero no van a ser atendidos, cuando salga de la otra interrupcion y se activen la interrupcion global, al tener alguna flag en 1 (y obviamente habilitada para ese modulo) va a re-entrar a la interrupcion.
- ¿Las flags pueden estar en 1 sin activar las interrupciones?
SI, nada evita que las flags cambien a 1. Pero sino estan activas las interrupciones del modulo Y global no va a saltar al vector de interrupcion
PD: Perdon por todos los horrores ortográficos, es que lo hago rápido mientras tengo un tiempito libre.
PD2:
los explica de una forma bastante superficial incluyendo los apuntes que él mismo preparó.
No se en que nivel estas. Soy docente de secundaria, pero no de electronica, sino de matematica y Fisica, no te imaginas el dolor de cabeza que es desarrollar todo para que luego no te lo lean o te digan "no entiendo". Incluso con clases virtuales. Por supuesto esto no es valido para todos los alumnos.
Cualquier otra pregunta es bienvenida.