.: Codificando interrupciones
Ya estoy de regreso nuevamente, y a ver quién me sigue... que esta vez haré un programa que a muchos les puede resultar bobo, así que... a no criticar, que ya lo advertí...
Comenzamos...???
Bien, el programa consiste en preparar todo para el encendido de un LED que conectaremos en RB1, pero como dije, sólo prepararemos todo, porque luego haremos dormir al micro hasta que interrumpamos su sueño para atender un pulsador conectado a RB0/INT, momento en el cual deberá encender el LED, y regresar a dormir nuevamente, y cuando vuelvas a presionar el pulsador haremos que lo apague y otra vez lo despacharemos a dormir.
Esto ya lo hicimos anteriormente, sólo que ahora lo haremos con interrupciones, ok...???
Allá vamossss...!!!
;---------------Encabezado-------------
LIST P=16F84
#include <P16F84.INC>
;-------Configuración de puertos-------
ORG 0x00
GOTO inicio
ORG 0x04
GOTO ISR
ORG 0X05
inicio BSF STATUS,RP0 ; configurando puertos
MOVLW 0x01 ; carga w con 0000 0001
MOVWF TRISB ; RB0/INT es entrada
BCF OPTION_REG,6 ; seleccionamos flanco descendente
BCF STATUS,RP0
;-------Habilitación de interrupciones-------
BSF INTCON,GIE ; habilitamos todas las interrupciones
BSF INTCON,INTE ; que sean interrupciones externas
CLRF PORTB ; limpio el puerto B
sueño SLEEP
GOTO sueño ; Dulces sueños...!!!
;-------------Rutina de servicio de interrupciones-------------
ISR BTFSC PORTB,0 ; verificamos que suelten el pulsador
GOTO ISR
BTFSC PORTB,1 ; y ahora sí, si el led está a 1
GOTO off_led ; ire a off_led para apagarlo
BSF PORTB,1 ; sino, enciendo el LED
BCF INTCON,INTF ; borro bandera de interrupción
RETFIE
off_led BCF PORTB,1 ; apago el LED
BCF INTCON,INTF ; borro bandera de interrupción
RETFIE
;------------------------------------------
END
;------------------------------------------
|
|
Desde nuestros primeros tutoriales hemos alcanzado a conocer varias de las instrucciones que se encuentran en este trozo de código, razón por la cual no las describiré, así es que vamos por aquello que está en rojo...
ORG 0x04
GOTO ISR
La primera línea es el vector de interrupción, y cuando ésta se produzca, el código de programa apuntará a esta dirección y continuará con la siguiente instrucción, es decir GOTO ISR, la cual es un salto a ISR (Rutina de Servicio de Interrupciones) para atender dicha interrupción.
Configuramos el puerto B, como habrás notado, hemos configurado RB0/INT como entrada y el resto de los bits como salida, luego...
BCF OPTION_REG,6 seleccionamos flanco descendente
En la página anterior dijimos que podíamos seleccionar el flanco con el cual se producirá la interrupción, pues eso es lo que estamos haciendo con esta instrucción, entonces vamos al registro OPTION y ponemos el BIT6 a "0" de este modo la interrupción se producirá cuando suelten el pulsador.
Ahora pasamos a lo más interesante, la habilitación de las interrupciones...
BSF INTCON,GIE ; habilitamos todas las interrupciones
BSF INTCON,INTE ; que sean interrupciones externas
Observa que la habilitación de interrupciones se hace en el banco0 ya que el Registro INTCON se encuentra en este banco. Bien, En la primera línea hacemos una habilitación general de todas las interrupciones, hacemos GIE=1, en la segunda línea, habilitamos interrupciones externas, hacemos INTE=1, recuerda que la bandera para la interrupción por el pin RB0/INT es INTF, no lo olvides, pues esta cambiará cuando la interrupción se produzca y luego de atenderla deberemos volverla a cero.
Lo que viene ahora es simplemente limpiar el puerto B, y luego...
sueño SLEEP
GOTO sueño
SLEEP es la instrucción que pone al micro en estado de bajo consumo, es como que todo se detiene y éste pasa a modo de reposo, (consulta el set de instrucciones para mayor detalle...) debí haber puesto simplemente SLEEP pero veamos, si se ejecutaría la instrucción SLEEP el micro entraría en reposo hasta que se produce la interrupción, lo cual dijimos anteriormente que es como una llamada (un call), cuando regrese se encontrará con GOTO sueño y lo volveremos a dormir.
Te imaginas...??? si no pusiéramos el GOTO sueño, cuando regrese de la interrupción pasaría a la ISR (Rutina de servicio de interrupción), y lo peor de todo, es que lo haría sin que se produzca la interrupción, gran dolor de cabeza...!!!
Pero bueno, ahora nos quedamos a dormir con el micro hasta que un chico travieso active el pulsador de RB0/INT ...Felices sueñosssss...!!!!
chico malo...!!!, que siempre me pones a prueba, Ya veo que no pudiste esperar y presionaste el pulsador...
De acuerdo... sabes a donde me llevaste...??? justo a...
ORG 0x04
GOTO ISR
Entonces vamos hacia allá, ahora te daré para que tengas, guardes y repartas...
Lo que viene, es la rutina de servicio de interrupción ISR y comenzamos con un...
ISR BTFSC PORTB,0 ; verificamos que suelten el pulsador
GOTO ISR
ISR no es una instrucción, sino la etiqueta que atiende la interrupción (pude haber puesto rut_serv u otra cosa, en fin...). Con BTFSC PORTB,0, prevenimos los rebotes, no se si era necesario ya que seleccionamos flanco descendente para este pin, pero por si las moscas lo puse, en realidad suele pasar que cuando se libera el pulsador se genera una pequeña chispa, la cual ya conocemos como rebote eléctrico, sólo lo puse por prevención.
Ahora si atenderemos la interrupción, comenzando por...
BTFSC PORTB,1
BTFSC PORTB,1 es probar si el segundo bit (Bit1 de PORTB) está en 0, es decir si el LED está apagado y saltar un línea si es así.
En lecciones anteriores utilizamos un registro llamado cont con el cual sabíamos si el LED estaba prendido o apagado, y aquí tienes una forma de optimizar ese código, espero que no te pierdas con esto...!!!
Bien... como recién iniciamos, el LED está apagado, por lo tanto saltamos una línea y pasamos a...
BSF PORTB,1
es decir hacemos RB1=1 (prendemos el LED). Perfecto, la interrupción ya fue atendida, pero ahora debemos habilitarla de nuevo así permitimos que se vuelva a ejecutar, y como tenemos un único pulsador el cual me cambió la bandera INTF, deberemos borrarla nuevamente, así es que...
BCF INTCON,INTF ; borro bandera de interrupción
Obviamente al producirse la interrupción se hizo GIE=0 para darnos lugar a atenderla, entonces...
RETFIE
y ahora GIE=1, las interrupciones están nuevamente habilitadas la bandera de RB0/INT está lista para una nueva interrupción y retornamos a ...
sueño SLEEP
GOTO sueño
y esperaré a que pulses RB0, pues si ya lo hiciste habrás ido por segunda vez a ...
ORG 0x04
GOTO ISR
prevenimos los rebotes y luego vamos a...
BTFSC PORTB,1
es decir, prueba y salta si el Bit1 de PORTB es cero, y como esta vez el LED está prendido... simplemente harás un...
GOTO off_led ; ire a off_led para apagarlo
un salto a la etiqueta off_led...
off_led BCF PORTB,1 ; sino, apago el LED
no se si requiere explicación pero bueno, pones a cero el Bit1 de PORTB. Finalmente...
BCF INTCON,INTF ; borro bandera de interrupción RETFIE
Ahora estamos listos para comenzar de nuevo...
te gustó...???, bieeeenn, aplausos para quien logró comprender...
y ahora la pregunta del millón...
que pasó con el mapa de memoria...???, donde se definieron las posiciones de memoria para los registros TRISB, PORTB, el registro OPTION..??? y el INTCON...???, donde demonios se definieron estas posiciones de memoria que supuestamente deben estar en el encabezado...???
No me digas que no te percataste de eso...!!! :-O
La respuesta la tendremos en el próximo tutorial, y por la misma web ...ahí nos vemosssss...!!!
:o))
R-Luis...
<-- Anterior
Introducción
Siguiente -->
Tabla de Referencias
|