Você está na página 1de 6

LAS INTERRUPCIONES

en los PIC
Hoy es: Viernes, 22 de Enero del 2010__________________ Incluir en favoritos si
quiere volver a visitarnos.

Introducción.
Hemos avanzado en nuestro empeño de aprender un poco mas a cerca de la programación
de los micros PIC y no podemos continuar sin atender unas de las más importantes
instrucciones ("herramientas") como son las interrupciones. Veremos que hay dos tipos de
interrupción en los micros PIC16X84 y vamos a descubrir como podemos usarlas en
nuestro provecho.

Las Interrupciones.

Es una de las características de los microcontroladores, de las más importantes que


constituye la capacidad de sincronizar la ejecución de programas con acontecimientos
externos; es decir, cuando se produce una interrupción, el micro automáticamente deja lo
que esté haciendo, va a la dirección 04h de programa y ejecuta lo que encuentre a partir de
allí hasta encontrarse con la instrucción RETFIE que le hará abandonar la interrupción y
volver al lugar donde se encontraba antes de producirse dicha interrupción. Hemos de
diferenciar entre dos tipos de interrupciones posibles en un PIC16X84:
1. - Mediante una acción interna. El desbordamiento de la Pila (Stack) por una operación
indebida, por ejemplo:
Al completarse la escritura de datos en una EEPROM.
Por desbordamiento del registro TMR0 al rebasar el valor 255 (FFh) a 0.
2. - Mediante una acción externa, la más útil. Al producirse un cambio del nivel en uno de
sus pines por una acción externa.
Estando en el modo de reposo (SLEEP), un cambio de nivel en el pin RB0/INT .
Un cambio de nivel en uno de los pines RB4 a RB7 estando configurados como entrada.

Cuando ocurre un evento de los descritos anteriormente, se produce una petición de


interrupción, guardando el valor actual del PC (contador de programa) en la Pila, sea cual
sea la fuente de la interrupción, se pone a cero el bit7 GIE (Global Interrupt Enable), con
lo cual inhibe cualquier otra petición de interrupción, el registro PC se carga con el valor
0004h que, es la posición del vector de interrupción. Aquí, empieza la ejecución del
programa de atención a la interrupción ISR (Rutina de Servicio de Interrupción). El tiempo
de procesamiento de la ISR debe ser lo más breve posible, para que se ejecuten las otras
interrupciones ya que, pueden habilitarse más de una de ellas. Además, cualquier tipo de
interrupción también puede sacar al micro del modo de reposo (SLEEP).
Como he apuntado, una interrupción puede ser inhibida sólo si existe otra interrupción en
curso. Esto se debe a que, una interrupción está controlada por dos bits que indican la
fuente de la interrupción, un bit actúa como bandera (flag) indicando si se ha producido
una interrupción y el otro bit, actúa como bit de inhibición o prohibición de la interrupción
en sí, debido a que existe otra interrupción en ejecución y todo esto se realiza de forma
automática por parte del micro.

Ecir, el bit GIE es el responsable del permiso de interrupción que se borra


automáticamente cuando se acepta una interrupción evitando así que se produzca ninguna
otra interrupción mientras se atiende a la primera. Estos bits de control se encuentran en el
registro INTCON (0Bh y 8Bh). Estos bits corresponden al registro INTCON que cambia
de nivel 0 a 1 cuando se produce la interrupción, excepto el último bit (bandera) que se
encuentra en el registro EECON1. Véase los detalles de los bits de INTCON.

REGISTRO INTCON
1 = Todas las
Interrupciones
habilitadas
Bit7 GIE 0 = Todas las
Bit Enabled Interrupt Global
Interrupciones
inhábiles
1 = Habilitación
Bit Interrupciones de
Bit6 EEIE Activada
Periféricos
0 = Desactivada
1 = Habilitación
Bit5 T0IE Activada Bit Interrupción del TMR0
0 = Desactivada
1 = Habilitación
Bit4 INTE Activada Bit Interrupción externa
0 = Desactivada
1 = Habilitación
Interrupción por cambio
Bit3 RBIE Activada
Puerto B
0 = Desactivada
1 = TMR0
 Bandera del TMR0
Bit2 T0IF desbordado
0 = No desbordado - Borrar por software
1 = Hubo
interrupción
externa  Bandera RB0/INT
Bit1 INTF 0 = No hubo - Borrar por software
interrupción
externa
1 = Uno o más
pines cambiaron de  Bandera en RB4 :
Bit0 RBIF nivel RB7
0 = Ningún pin ha - Borrar por software
cambiado de nivel.
Las acciones que debe tener en cuenta el programador al crear sus programas, son las
siguientes:
1. Cuando se produce una interrupción el bit7 GIE se pone a 0.
2. El valor del PC se guarda en la Pila (Stack) con el valor 0004h, que
es el vector de interrupciones.
3. La rutina de atención a la interrupción debe empezar con un salto a la
posición de memoria de programa, antes, debe guardar todos los registros
que puedan ser modificados por la interrupción y explorar las banderas para
determinar la causa de la interrupción.
4. Dependiendo de la causa, la rutina de interrupción se bifurcará a la
subrutina correspondiente.
5. Antes de volver al programa principal, se deben devolver los valores
originales salvados de los registros anteriores a la interrupción y además
limpiar (poner a 0) las banderas que indican la fuente de la misma.
6. Como última instrucción de la rutina de interrupción usar RETFIE,
que cargar el PC con el valor de Pila y el bit GIE se pondrá
automáticamente a 1.
 Para detectar interrupción: TOIF (bandera (Flag) de interrupción por
desbordamiento de TMR0)
 Para habilitar interrupción: TOIE (habilita la interrupción por desbordamiento de
TMR0)

Por tanto, el bit7 GIE, es el encargado de la activación global que habilita las
interrupciones al ponerse a 1 y al reconocer una interrupción se pone a 0 de forma
automática, evitando se produzca otra interrupción mientras se atienda la actual. El bit GIE
se pone de nuevo a 1 al retornar de la atención a la interrupción al encontrar una instrucción
RETFIE. Para el resto de los bits (banderas o flags) no está previsto ningún tratamiento de
puesta a cero, por lo que es el propio programa de atención a la interrupción, el que le
corresponde tratarla y las banderas (flags) que indican la interrupción, debe ponerlas a 0
(cero).

Antes de seguir, hago hincapié en que, si bien cada bandera cambia o se pone a 1 al
producirse una interrupción, es tarea del propio programador, borrarla o ponerla a cero
nuevamente, ya que si no lo hace, el micro siempre permanecerá interrumpido o lo que es
lo mismo, creerá que la interrupción se está produciendo continuamente.

En resumen, el micro sólo tiene un vector de interrupción en la dirección 0x04h, así que,
con cualquier interrupción el PC se carga con 0004h y el programa de atención a la
interrupción (que llamamos ISR) se encarga de comprobar el estado de las banderas para
determinar que dispositivo causó la interrupción y actuar según lo previsto, la propia ISR
se encargará de guardar los registros implicados al principio de la rutina para poder
devolver sus estados originales al regresar de la rutina. Ver el siguiente ej.

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
; Nombre: Demo de Interrupciones ^
; Que hace => Encender un LED en RB1, lo haremos dormir y ^
; despertarlo al accionar un pulsador en RB0/INT lo encenderá para ^
; hacerlo dormir hasta la siguiente interrupcion que lo apagará. ^
; --- Descripcion del circuito --- ^
; El pin 7 (RB1) conectado al anodo del LED, el catodo a masa. ^
; El pin 6 (RB0/INT) conectado a positivo a traves de R de 10K ^
; El pin 6 (RB0/INT) conectado a contacto pulsador, el otro a masa.^
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LIST P=16F84
#include <P16F84a.INC>
ACUM equ h'000C' ;se declara acum
STAT equ h'000D' ;se declara stat

#DEFINE BANCO0 BCF STATUS,5

Org 0x00 ;Posicion 0 de la Memoria de Programa (apuntador)


;Viene cuando hay una interrupcion.
goto inicio ;Va a la etiqueta INICIO

ORG 0x04 ;viene cuando hay una interrupcion


GOTO rsi ;salta a rutina de rsi que atiende la interrupcion
ORG 0X05

; ****Bits del registro OPTION *******************************


; bit8 = 0 Resistencias de polarización deshabilitadas
; bit7 = 0 Interrupción externa por flanco bajada (no usada)
; bit6 = 0 Fuente de reloj, interno (Usa TMR0 como temporizador)
; bit5 = 0 Flanco de señal externa (no lo usamos)
; bit4 = 0 Divisor asignado al TMR0
; bit3 = 1 bit2 = 1 bit1 = 0 División por 128
; *******************************************************

;---- Inicio ------


ini BSF status,RP0 ; configurando puertos
MOVLW 01 ; carga w con 0000 0001
MOVWF trisb ; RB0/INT es entrada
BCF option_reg,6 ; seleccionamos flanco descendente
BCF status,RP0
;---- Activa interrupciones ----
BSF intcon,GIE ; habilita todas las interrupciones
BSF intcon,INTE ; que sean interrupciones externas
CLRF portb ; limpia el puerto B
dormir SLEEP
GOTO dormir ; poner a dormir
;---- rutina servicio interrupciones
rsi BTFSC portb,0 ; verifica que se suelte el pulsador
GOTO rsi ; espera
; comenzamos guardando el contenido del W
MOVWF ACUM ; Copia el acumulador al registro acum
MOVF status,W ; Guarda STATUS en el acumulador
BANCO0 ; para restaurarlos antes de volver
MOVWF STAT ; Copia el acumulador al registro STAT

BTFSC portb,1 ; y ahora sí, si el led está a 1


GOTO off_led ; ir a off_led para apagarlo
BSF portb,1 ; sino, encender el LED
BCF intcon,INTF ; borrar bandera de interrupción
GOTO HECHO ; salta a restaurar valores
RETFIE ; antes de volver

off_led BCF portb,1 ; apaga el LED


BCF intcon,INTF ; borra bandera de interrupción
; Restauramos los valores del W y status
HECHO MOVF STAT,W ; Guarda el contenido de STAT en el W
MOVWF STATUS ; Restaura el STATUS
SWAPF ACUM,F ; Da la vuelta al registro ACUM
SWAPF ACUM,W ; Vuelve a dar la vuelta al registro ACUM
; y lo restaura

RETFIE ; retorna al programa principal


END

Como referencia, debemos guardar el contenido del registro W y del registro STATUS,
para lo cual "no se debe usar la instrucción MOVF" porque corrompe la bandera Z,
modificando el registro STATUS. En las hojas del fabricante recomienda el código del
siguiente ej. a la hora de tratar una rutina de servicio de interrupciones y puede tomarse, de
forma general, procurando adaptarlo a la exigencia del usuario.

; ======== Inicio - Rutina de Servicio de Interrupción =========


; ========== Guardando W y el Registro de Estado ==========

MOVWF R_W ; Guardamos W en R_W (R_W=0x0A)


SWAPF STATUS,W ; invertimos los nibbles del registro STATUS
(STATUS=0xAF) y
; lo pasamos a W, (W=0xFA). Si ponemos f en SWAPF STATUS,f
; se guardara en el mismo registro STATUS
MOVWF R_STAT ; Guardamos el contenido de STATUS en
(R_STAT=0xFA)
. .
. . ; Aqui atendemos la rutina ISR
. . ; Deberia configurarse banco como se requiera

; ======== Fin - Rutina de Servicio de Interrupción ===========


; ======== Restaurando W y el Registro de Estado ===========

SWAPF R_STAT,W ; invertimos los nibbles del registro R_STAT


; y lo pasamos a W (R_STAT=0xFA), (W=0xAF)
MOVWF STATUS ; Restauramos STATUS (STATUS=0xAF)
; estado original del banco
SWAPF R_ACUM,F ; invertimos los nibbles de R_ACUM (R_ACUM=0xA0)
que
SWAPF R_ACUM,W ; invirtiéndolo nuevamente lo pasamos a W, ahora
W=0x0A
;
RETFIE

En este ejemplo; R_W y R_STAT son registros auxiliares en los que se guardan los valores
del registro W y del registro Status. Lo que se ha hecho:
 Se guarda el registro W en R_W
 Se guarda el registro STATUS en R_STAT
 Se ejecuta la rutina de servicio de interrupciones. Y antes de salir de la ISR
 Se restablece el registro STATUS (y el bit seleccionado del banco)
 Se restablece el registro W

Espero que se haya aprovechado la descripción del tema de las interrupciones y los
registros que de algún modo se relacionan con las mismas, para avanzar en los
conocimientos de la programación. En próximos artículos veremos como aplicar estos
conocimientos.

Você também pode gostar