LAS INTERRUPCIONES
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.
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.
|
Las acciones que debe tener en cuenta el programador al crear sus programas, son las siguientes:
Cuando se produce una interrupción el bit7 GIE se pone a 0.
El valor del PC se guarda en la Pila (Stack) con el valor 0004h, que es el vector de interrupciones.
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.
Dependiendo de la causa, la rutina de interrupción se bifurcará a la subrutina correspondiente.
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.
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.
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 o 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:
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.
Volver al índice de artículos PIC.