Manejo de Interrupciones
1
7.1. Introducción Se le llama interrupción a un salto especial a una subrutina que no está contemplado en un punto específico del programa principal, sino que puede ocurrir en cualquier punto de éste y no es provocado por una un a instrucción en el programa, sino por un evento interno o externo al sistema del microcontrolador. Es decir, una interrupción es una técnica particular del PIC que permite: interceptar eventos externos de un programa en ejecución, interrumpiendo momentáneamente la operación del programa, controla el evento con una subrutina apropiada, y retorna para continuar con la ejecución del programa en el punto donde se produjo la interrupción. i nterrupción. Los dispositivos que manejan eventos capaces de provocar una solicitud de interrupción se denominan fuentes de interrupción. La familia del PIC16F87x cuenta con hasta 14 fuentes de interrupción, de las cuales algunas de ellas se habilitan por medio del registro de control INTCON, otras, sin embargo, como la del convertidor A/D se encuentra en el registro PIE1, en este mismo registro está está el bit del TIMER1 (TMRIE ,PIE1<0>) entre otros. En el registro INTCON sólo se encuentran tres controles de interrupciones. Interrupciones ocasionadas en la patilla RBO/INT, las ocasionadas por cambios de estado en las patillas RB7:RB4 y las que tienen lugar por el desbordamiento del temporizador TMR0, el resto de los controles de periféricos y funciones especiales se encuentran en los registros PIR1, PIR2. El bit GIE (INTCON<7>) habilita las interrupciones no enmascaradas, por el contrario, cuando está a cero, deshabilita todas las interrupciones interrupciones con independencia independencia de cómo se encuentren encuentren los bits individuales de interrupciones. Cuando tiene lugar una interrupción, el valor del Contador de Programa ( PC) se envía al Stack y se carga con 0004 hex (vector de interrupción). El microcontrolador microcontrolador comenzar a ejecutar las instrucciones de la subrutina de interrupciones y cuando se encuentre una instrucción RETFIE dará por finalizada la subrutina volviendo a la siguiente dirección de la última instrucción ejecutada antes de producirse la interrupción. Hay que tener en cuenta que cuando se produce un Reset se borra el bit GIE, por lo que se deshabilitan todas las interrupciones, aunque se habiliten los bit s individuales. Al atender una interrupción, el bit GIE se borra automáticamente con lo que se deshabilita la posibilidad de futuras futuras interrupciones, la dirección de retorno retorno se envía al Stack y el Contador de Programa se carga con con la dirección 0004 hex. (vector de interrupción). En esta dirección comenzará la subrutina de servicio servicio de interrupciones. Para determinar qué periférico o función ha ocasionado la interrupción se deberán leer los bits de control de las correspondientes interrupciones Cada fuente de interrupción posee dos bit s asociados a ella: •
•
Una Bandera (terminada en F) de Interrupción, la cual es activada (en alto) por el evento para solicitar una interrupción. Una Máscara (terminada en E) Local de Interrupción, la cual si está desactivada (en bajo) bloqueará l a solicitud de interrupción i nterrupción correspondiente, pero si está activada 2
•
•
(en alto) permitirá la solicitud de Interrupción. Además existe una máscara de interrupción global GIE (INTCON<7>), la cual bloqueará todas las solicitudes de interrupción si está desactivada ( GIE=0). Algunas fuentes de interrupción también poseen una segunda máscara de interrupción global denominada PEIE (INTCON<6>) . De hecho, actúa sobre todas las fuentes de interrupción, excepto las interrupciones debidas a la patita INT, el sobre flujo del Timer 0 y las interrupciones del puerto B (INTF, T0IF y RBIF).
De acuerdo a lo anterior, la única manera en que una solicitud de interrupción provoca en efecto una interrupción en el programa es cuando: • • • •
La máscara global está activada ( GIE=1). (En su caso) la máscara global de periféricos está activada ( PEIE=1) La máscara local está activada Ocurre un evento que activa la bandera correspondiente. cor respondiente.
7.2. Tipos de Eventos y Bits de Habilitación En el registro INTCON registro INTCON sólo sólo se encuentran tres controles de interrupciones: 1. Un cambio de estado sobre la línea RB0 ( pin de interrupción i nterrupción externa RB0/INT ) 2. Desbordamiento de la cuenta del registro TMR0 ( TMR0 overflow interrupt ) 3. Un cambio de estado sobre una de las líneas de RB4 a RB7 ( PORTB change interrupts ). Los cuales se describen a continuación:
1. Interrupción de TMR0 Si el temporizador TMR0 se ha desbordado, el flag de overflow (T0IF) del registro INTCON se habrá puesto a uno. Es evidente que previamente previamente se habrán borrado todos los flags que pudieran ocasionar una interrupción, así se evitarán interrupciones recursivas. Para habilitar esta interrupción se debe poner en 1 el bit T0IE.
2. Interrupción externa por RB0/INT Las transiciones de bajo a alto, o viceversa, de la patilla RB0/INT puede ocasionar una interrupción, el flanco que la producirá producirá se elige con con el bit INTEDG (OPTION_REG<6>). Cuando este bit bit se pone a uno, la interrupción interrupción tendrá lugar en la transición de cero a uno, uno, por el contrario, el flanco de bajada bajada ocasionará la interrupción cuando el bit se coloque a cero. cero. En cuanto tenga lugar en la patilla RB0/INT el flanco elegido, el bit INTF (INTCON<1>) se pondrá a uno; el estado de los bits de interrupciones globales ( GIE) e interrupción externa ( INTE) determina si se atenderá o no la interrupción. interrupción. Si están habilitadas habilitadas y el microcontrolador se encuentra encuentra en reposo reposo (Sleep) éste despertará.
3. Interrupción por cambio de estado en RB4:RB7 Además de la interrupción externa descrita, estos microcontroladores se disponen de otro modo de ocasionar una interrupción externa; cualquier cambio de estado q ue se produzca 3
en las patillas RB7:RB4 también la ocasionará, ocasionará, para habilitarla, hay que poner poner a uno el flag de interrupciones RBIE (INTCON<3>). Cualquier cambio cambio de estado estado que haya en estas patillas hará que el bit RBIF (INTCON<0>) se ponga a uno y se produzca la interrupción. Para que el sistema pueda ocasionar una interrupción por cambios de estado en las patillas RB7:RB4 es necesario realizar algunas actuaciones previas que no son necesarias en otro tipo de interrupciones ya que el estado de estas cuatro patillas es comparado continuamente, en la fase Q1 del reloj, con el estado previo de los latch del puerto. Por consiguiente, consiguiente, antes de habilitar esta interrupción interrupción habrá que leer o escribir en él para que su contenido se quede almacenado en los latch; solamente los bits configurados como entradas se comparan y si son diferentes a los previamente almacenados pueden ocasionar una interrupción. El resto de los controles de periféricos y funciones especiales se encuentran en los registros PIR1 , PIR2 (Banderas) (Banderas) y PIE1 , PIE2 (Mascaras) (Mascaras). Una interrupción de cualquiera de estos eventos puede ser conseguida habilitando o deshabilitando independientemente independientemente los siguientes bits de los registro INTCON, PIR1 y , PIR2: •
•
•
•
• • • • • • •
• • •
INTE. Si este bit está en 1 habilitará habilitará la interrupción de cambio de estado estado sobre la línea RB0 T0IE. Si este bit está está en 1 habilitará habilitará la interrupción de final de conteo conteo del registro TMR0 RBIE. Si este bit está en 1 habilitará la interrupción de cambio cambio de estado sobre sobre una de las líneas de RB4 a RB7 EEIE. Si este bit está está en 1 habilitará la interrupción de de final de escritura sobre la EEPROM PSPIE. Si este bit está en habilitará la interrupción por lectura/escritura en el PSP ADIE. Si este bit está en 1 habilitará la l a interrupción del convertidor A/D RCIE. Si este bit está en 1 habilitará interrupción por recepción en el USAR TXIE. Si este bit está en en 1 habilitará la interrupción de transmisión por el USAR SSPIE. Si este bit está en 1 habilitará la interrupción del SSP CCP1IE. Si este bit está en 1 habilitará la l a interrupción del CCP1 TMR2IE. Si este bit está en 1 habilitará la interrupción por desbordamiento de TMR2 emparejado a PR2 TMR1IE. Si este bit está en 1 habilitará la interrupción por desbordamiento de TMR1 CCP2IE. Si este bit está en 1 habilitará la interrupción de CCP2 BCLIE. Si este bit está en 1 habilitará la interrupción por colisión de bus SSP
Existe otros dos bits de habilitación: •
•
Interrupción global GIE (INTCON<7>), la cual bloqueará todas las solicitudes de interrupción si está desactivada ( GIE=0) y si este bit está en 1 habilitará todas las interrupciones. Algunas fuentes de interrupción también poseen una segunda máscara de interrupción global denominada PEIE (INTCON<6>) . De hecho, actúa sobre todas las fuentes de interrupción, excepto las interrupciones: debidas a la patita INT, 4
el sobreflujo del Timer 0 y las interrupciones del puerto B (INTF, T0IF y RBIF).
7.3. Vector de Interrupción y Control de Interrupción Cualquier evento que sea habilitado, o se manifieste, el PIC interrumpe la ejecución del programa, almacena automáticamente en el STACK el valor actual del PROGRAM COUNTER y este pasa a ejecutar la instrucción presente presente en la dirección de memoria 0004H, denominada Interrupt Vector ( vector de interrupción ). Por lo tanto, tanto, desde este punto debemos colocar la llamada a la subrutina de control denominada Interrupt Handler ( control de interrupción ). Se puede habilitar varias interrupciones simultáneamente, porque la primera providencia del control de interrupción es la de verificar cuál evento habilitado genera la interrupción de la ejecución de parte del programa. Este control puede ser efectuado utilizando Interrupt Flag ( bandera de interrupción ).
7.4. Bandera de Interrupción Dado que cualquier interrupción genera una llamada a la dirección 04H, en los registros INTCON, PIR1 y PIR2 está presente varias banderas que indican cuál evento es el que genera la interrupción, las cuales se describen a continuación: Interrup. INTF
Descripción Externa. Se coloca en 1 cuando la interrupción INT ocurre, es decir cuando cambia de estado la línea RB0.
Registro INTCON
T0IF
Desbordamiento del TMR0. Se coloca en 1 cuando el TMR0 pasa de 00FFh a 00h, es decir cuando terminó de contar el timer T MR0
INTCON
RBIF
Por cambios en el PortB. Se coloca en 1 cuando una de las entradas ( RB4 a RB7 ) cambia, es decir cuando cambia de estado de una las líneas de RB4 a RB7
INTCON
EEIF
Finalización de escritura en la memoria EEPROM. Se coloca EEIF en 1 cuando la operación de escritura ha terminado, debe ser colocada a 0 por software.
PIR2
PSPIF
Lectura/Escritura puerto paralelo.
PIR1
ADIF
Convertidor A/D.
PIR1
RCIF TXIF
Recepción USAR.
PIR1 PIR1
Transmisión USAR.
SSPIF CCP1IF
Puerto Serie Síncrono. Capturador/Comparador 1.
PIR1 PIR1
TMR2IF
Temporizador TMR2.
PIR1
TMR1IF
Temporizador TMR1.
PIR1
CCP2IF
Capturador/Comparador 2.
PIR2
BCLIF
Indica la colisión en el bus SSP
PIR2
Importante. Una vez conocida cual de las banderas está activada, el control de interrupción debe generar la interrupción correspondiente.
7.5. Retorno de un control de interrupción 5
Cuando se genera una interrupción el PIC deshabilita automáticamente el bit GIE ( Global Interrupt Enable ) del registro INTCON, de modo que deshabilita todas las interrupciones restantes. Para poder retornar al programa principal y reinicializar este bit se debe utilizar la instrucción: RETFIE
7.6. Proceso de reconocimiento de una interrupción Cuando se cumplen las siguientes tres o cuatro condiciones simultáneamente: simultáneamente: • • •
•
El bit GIE está activado (en alto) El bit PEIE está activado acti vado (en alto), en las respectivos eventos Se produce un evento que solicita interrupción (se activa alguna de las banderas de interrupción) Está activada la máscara correspondiente a la bandera activada.
Entonces la CPU es interrumpida inmediatamente i nmediatamente y ejecuta lo siguiente: • •
• •
•
•
•
Termina la ejecución de la instrucción actual. Desactiva el bit GIE (GIE=0) para bloquear cualquier otra solicitud de interrupción. La dirección de programa de la siguiente si guiente instrucción a ejecutar es guardada en el stack. Ejecuta un salto a la localidad de programa 0004h denominada vector de interrupción, interrupción, en donde el usuario deberá haber colocado el inicio de la rutina de atención a la interrupción. interrupción. Ejecuta la rutina de atención a la interrupción escrita por el usuario, en la cual éste podrá constatar la fuente de interrupción consultando por poleo las banderas de interrupción. La rutina de atención a la interrupción deberá limpiar los bits de las banderas que solicitó la interrupción antes de rehabilitar las interrupciones, para evitar interrupciones recursivas. La rutina de atención deberá terminar con una instrucción RETFIE , la cual activa nuevamente el bit GIE (GIE=1) y lee el stack para continuar la ejecución del programa que fue interrumpido en la siguiente instrucción.
7.7. Diagrama lógico de las interrupciones La lógica de activación de máscaras y banderas descrita arriba puede entenderse en términos del diagrama lógico lógico mostrado en la siguiente figura. figura. En este diagrama diagrama se muestran las 14 fuentes de interrupción de los microcontroladores microcontroladores de la familia PIC16F87x y se usan los nombres específicos de cada fuente de interrupción para sus respectivas banderas y máscaras de interrupción.
6
La siguiente tabla se muestra las diferencias entre los dos modelos de 28 y 40 pines:
7.8. Salvar el contexto durante una interrupción Dado que el programa principal no puede prever en qué punto será interrumpido, la rutina de atención a la interrupción debe ser tal que no altere ninguno de los registros que requiere paso a paso el programa principal para su operación normal. Estos registros son los que van guardando el contexto del programa (tal como en qué banco está, el resultado de la última operación, etc.) y son: Registro STATUS Registro W Registro PCLATH (si se están usando las páginas 1, 2 o 3). Estos microcontroladores disponen de ocho niveles de Stack y cuando se produce una interrupción sólo se salva en él la dirección de retorno ( PC). Cualquier operación que que se realice en la subrutina subrutina de interrupciones podrá destruir, o modificar, el contenido de los datos almacenados en ciertos registros y que podrían ser necesarios cuando se retorne de la, subrutina subrutina de servicio de interrupciones. Si esto fuera así, se deberán guardar guardar los datos de los registros cuyo contenido sea de interés y que vayan a ser modificados a lo largo de la subrutina de servicio de interrupciones. Una vez finalizada la subrutina, subrutina, se deberán recuperar recuperar para que queden en en su estado original. Un ejemplo para salvar los registros de estado, W y PCLATH en memoria puede ser el siguiente: 7
El siguiente es un ejemplo del código que deberá incluirse al inicio y al final de la rutina de atención a la interrupción para salvar y recuperar el contexto: ;* Salva información de contexto previo a la ruitna de atención a la interrupción interrupción MOVWF W_Temp ;Salva el registro W en en un registro temporal SWAPF STATUS,W ;Copia STATUS en W (usa SWAP para no alterarlo al copiarlo) CLRF STATUS ;Banco cero, sin importar banco actual MOVWF STATUS_temp STATUS_temp ;Salva STATUS en STATUS_temp (Banco 0) ; MOVF PCLATH,W PCLATH,W ;sólo se requiere si se están usando las páginas 1,2,y/o 3 ; MOVWF PCLATH_temp PCLATH_temp ;salva PCLATH ; CLRF PCLATH ;página 0 sin importar página actual ... ;aquí se escribe el código de la rutina de atención a la interrupción ... ;* A continuación restablece la información de contexto que salvó al inicio ; MOVF PCLATH_Temp.,W PCLATH_Temp.,W ;rescata PCLATH ; MOVWF PCLATH PCLATH ;si se usan las paginas 1,2 y/o 3 SWAPF STATUS_temp,W ;rescata el STATUS original MOVWF STATUS STATUS ;restablece banco original SWAPF W_temp,F ;rescata el W original SWAPF W_temp,W ;sin alterar el STATUS ya rescatado. rescatado. RETFIE
El programa está está dividido en dos partes, partes, la primera guarda guarda el contenido de los registros y se ejecutan las instrucciones propias de la subrutina de servicio de interrupciones (comprobar quién ocasionó la interrupción, etc.) y la segunda recupera de la memoria los registros previamente almacenados. almacenados. La instrucción RETFIE llevará el flujo del programa a la dirección siguiente siguiente a la última instrucción ejecutada (recupera el PC del Stack) con los registros ya actualizados.
7.9. REGISTROS INVOLUCRADOS 1. REGISTRO INTCON (Dirección 0Bh, 8Bh, l0Bh, 18Bh) El registro INTCON es un registro de lectura y escritura que contiene los bit de habilitación de interrupciones por desbordamiento de TMR0 por cambio de nivel en el PORTB e interrupciones externas por la línea RBO/INT. R/W-0 GIE Bit 7
R/W-0 PEIE
R/W-0 T0IE
R/W-0 INTE
R/W-0 RBIE
R/W-0 T0IF
R/W-0 INTF
R/W-x RBIF Bit 0
bit 7:
GIE: bit de habilitación global de Interrupciones 1= Habilita el permiso de interrupciones 0= Inhabilita todas las interrupciones
bit 6:
PEIE: bit de habilitación de interrupciones de los periféricos que no se controla con el registro INTCON 1= Habilita el permiso de interrupciones de los periféricos 0= Inhabilita las interrupciones de los periféricos
bit 5:
T0IE: bit de habilitación de la interrupción por desbordamiento del TMR0
8
1= Habilita la interrupción 0= Inhabilita la interrupción bit 4:
INTE: bit de habilitación de la interrupción externa por el pin RB0/INT 1= Habilita la interrupción 0= Inhabilita la interrupción
bit 3:
RBIE: bit de habilitación de interrupción por cambio de nivel en el PORTB 1= Habilita la interrupción 0= Inhabilita la interrupción
bit 2:
T0IF: flag de indicación de desbordamiento de TMR0 1= El TMR0 se ha desbordado. Se borra por software 0= El TMR0 no se ha desbordado
bit 1:
INTF: flag de estado de la interrupción externa INT 1= La interrupción externa se ha producido. Se borra por software 0= La interrupción externa no se ha producido
bit 0:
RBIF: flag de indicación de interrupción por c ambio de nivel en PORTB 1= Se ha producido un cambio de nivel en los pines pines RB7:RB4. Se borra por software. 0= No se ha producido un cambio de nivel en los pines RB 7:RB4
2. REGISTRO PIR1 (Dirección 0Ch) El registro de PIR1 contiene los flags individuales que indican las interrupciones provocadas por los periféricos.
R/W-0 PSPIF Bit 7 bit 7:
R/W-0 ADIF
R/W-0 RCIF
R/W-0 TXIF
R/W-0 SSPIF
R/W-0 CCP1IF
R/W-0 TMR2IF
R/W-x TMR1IF Bit 0
PSPIF: Flag de Lectura/Escritura por el Puerto Paralelo esclavo
1= Concedido el permiso de interrupción para la puerta paralela esclava al realizar una operación de Lectrura/Escritura. Lectrura/Escritura. En los modelos de 40 pines 0= No está permitida la interrupción bit 6:
ADIF: Flag de final de conversión del convertidor A/D 1= El convertidor A/D ha finalizado la conversión 0= El convertidor A/D no ha finalizado la conversión
bit 5
RCIF: Flag de recepción por el USAR 1= El buffer de datos recibidos por el USAR está lleno 0= El buffer de datos recibidos por el USAR no está lleno
bit 4:
TXIF : Flag de transmisión el USAR 1= El buffer de datos a transmitir no está lleno 0= El buffer de daos a transmitir está lleno
9
bit 3:
SSPIF: Flag de interrupción del Puerto Serie Síncrono (SSP)
1= La condición del SSP ha ocurrido, debe ponerse a cero por software antes de volver del programa de atención a la interrupción. interrupción. Las condiciones condiciones que soporta este bit son: SPI
Ha tenido lugar una Transmisión / Recepción I2C Slave
Ha tenido lugar una Transmisión / Recepción I2C Master Ha tenido lugar una Transmisión / Recepción La condición de salida iniciada se completó por el módulo de SSP. La condición de parada inicio se completó por el módulo de SSP. La condición de reinicialización se completo por el módulo SSP Una condición de la salida se ha realizado mientras el módulo de SSP estaba en estado de espera (sistema de Multimaster). 0 = no ha ocurrido ninguna condición de interrupción del módulo SSP bit 2: CCP1IF: Flag de interrupción de CCPI Modo Captura
1= Ocurrió una captura de TMR1 (debe ponerse a cero por software) 0= No ocurrió ninguna captura de TMR1 Modo Comparación
1= Se ha realizado una comparación de TMR1 Con el registro emparejado /debe ponerse a cero por Software) 0= No se ha realizado comparación Modo PWM
Este modo no se utiliza bit 1:
TMR2IF : Flag de interrupción de TMR2 emparejado con PR2 1= TMR2 emparejado con PR2 ocurrió (debe ponerse a cero por software) 0= No ha ocurrido el emparejamiento de TMR2 con PR2
bit 0: TMR1IF: Flag de desbordamiento de TMRI 1 =el registro se desbordo (debe ponerse a cero por software) 0 = el registre¡ de TMRI no se desbordo
Nota 1. PSPIF está reservado para los dispositivos de 28 pines; se mantiene siempre a cero. 3. REGISTRO PIR2 (Dirección 0Dh) El registro de PIR2 contiene los flags que indican la interrupción del CCP2, de la colisión del bus SSP y la interrupción de la escritura en la EEPROM
U-0 --Bit 7
R/W-0 (1)
U-0 ---
R/W-0 EEIF
R/W-0 BCLIF
U-0 ---
U-0 ---
R/W-x R/W -x CCP2IF Bit 0
bit 7:
No implementado: se lee como “0”
bit 6:
Reservado : Mantiene este bit siempre a cero
10
bit 5:
No implementado: se lee como “0”
bit 4:
EEIF: Flag que indica si se ha producido escritura en al EEPROM 1 = Se ha completado la escritura en la EEPROM (Se pone a cero por software) 0 = No se ha finalizado la escritura o no se ha comenzado
bit 3:
BCLIF: Flag que indica la colisión en el bus 1 = Se ha producido una colisión en el bus SSP, cuando se configura en el modo I2C Master. 0 = No se ha producido colisión en el bus
bit 2-1:No implementados: se leen como “0” bit 0: CCP21F: Flag de ininterrupción de CCP2 Modo Captura 1 = Ha ocurrido una captura del registro TMR1 (debe ponerse a cero por software) 0= No se ha producido captura Modo Comparación 1 = Se ha producido una comparación de TMR1 con su pareja (debe ponerse a cero por software). 0 = No se ha producido comparación Modo PWM No se utiliza
4. REGISTRO PIE1 (Dirección 8Ch) Este registro contiene los bits individuales de habilitación de interrupciones de los periféricos.
Nota. El bit PEIE (INTCON <6>) debe esta a uno para habilitar las interrupciones de cualquiera de los periféricos. R/W-0 (1) PSPIE Bit 7
R/W-0 ADIE
R/W-0 RCIE
R/W-0 TXIE
R/W-0 SSPIE
R/W-0 CCP1IE
R/W-0 TMR2IE
R/W-0 TMR1IE Bit 0
bit 7:
PSPIE: bit de habilitación de interrupción por lectura / escritura en el Puerto Paralelo Esclavo. Para los modelos de 40 pines. 1 = Habilita la interrupción por lectura/escritura en el PSP 0= inhabilita la interrupción por lectura/escria en el PSP
bit 6:
ADIF: bit de habilitación de interrupción por finalización de la conversión A/D l = Habilita la interrupción del convertidor A/D 0 = Inhabilita la interrupción del convertidor A/D
bit 5:
RCIE: bit de habilitación de interrupción en recepción por el USAR, cuando se llena el buffer, 1 = Habilita interrupción por recepción en el USAR 0 = Inhabilita interrupción por recepción en el USAR
bit 4:
TXIE: bit de interrupción al transmitir por el USAR, cuando se vacía el buffer.
11
1 = Habilita la interrupción de transmisión transmisión por el USAR 0 = Inhabilita la interrupción de transmisión por el USAR bit 3:
SSPIE: bit de habilitación de interrupción por el Puerto Serie Síncrono (SSP) 1= Habilita la interrupción del SSP 0= Inhabilita la- interrupción del SSP
bit 2: CCP1IE : bit de habilitación de interrupción del módulo CCPI cuando se produce una captura o una comparación. 1= Habilita la interrupción del CCPI 0=. Inhabilita la interrupción del CCPI bit 1:
TMR2IE: bit de habilitación de interrupción por desbordamiento de TMR2 que está emparejado con el registro PR2 (92h) 1= Habilita la interrupción por desbordamiento de TMR2 emparejado a PR2 0= Inhabilita la interrupción de TMR2 emparejado a PR2
bit 0:
TMR1IE: bit de habilitación de interrupción por desbordamiento del TMRI 1= Habilita la interrupción por desbordamiento de TMR1 0= Inhabilita la interrupción por desbordamiento de TMR1
Nota 1. PSPIE para los dispositivos de 28 pines, siempre mantiene este bit a cero. 5. REGISTRO PIE2 (Dirección 8Dh) El registro de PIE2 PIE2 contiene los bits individuales que habilita las interrupciones interrupciones del del periférico CCP2, la interrupción por por colisión del SSP y la interrupción de escritura escritura en la EEPROM. U-0 --Bit 7
R/W-0
0
U-0 ---
R/W-0
EEIE
R/W-0 BCLIE
U-0 --
U-0 --
R/W-0 CCP2IE Bit 0
bit 7:
No implementado: se lee como “0’
bit 6
Reservado , Mantiene este bits a cero
bit 5:
No implementado: se lee como “0”
bit 4:
EEIE: Habilita la interrupción por escritura en la EEPROM de datos 1= Habilita la interrupción por escritura de la EEPROM de datos 0 =Deshabilita la interrupción por por escritura en la EEPROM de datos
bit 3:
BCLIE: Habilita la interrupción por colisión en el bus SSP cuando dos o más maestros tratan de transferir al mismo tiempo. 1 = Habilita la interrupción por colisió n de bus SSP 0 = Deshabilita la interrupción interrupción por colisión en el bus SSP.
bit 2-1 No implementados, se leen como “0”
12
bit 0:
CCP2IE : Habilita la interrupción del modulo CCP2 1 = habilita la interrupción de CCP2 0 = inhabilita la interrupción de CCP2
Ejemplo 1 Medidor de periodo mejorado por Interrupciones Como ya se dijo para el ejemplo Medidor de periodo del Modo captura , éste tiene limitantes muy grandes especialmente en el límite límit e superior de frecuencia que n o puede procesar correctamente, debido a que durante el tiempo empleado en la transmisión del dato no puede detectar ninguna transición de la señal de entrada. Esto puede corregirse si primero se detecta la captura y con la interrupción de ésta se realiza la transición. La modificación se muestra en el siguiente listado. ;********************** ;********************************** ************************ ************************* ****************** ***** ;* Este programa mide el periodo de una señal oscilatoria en la * ;* patita RC2/CCP1. Por INTERRUPCIONES generadas por la captura * ;* de cada transición de 0 a 1 en dicha patita. * ;* El valor de periodo capturado representa el número de ciclos * ;* Tcy por periodo. Dicho valor se envía continuamente continuamente por * ;* el puerto serie. Se supone un cristal de 14.7456 Mhz * ;********************** ;********************************** ************************ ************************* ****************** ***** Include "p16f877.inc" msnib EQU 0x20 lsnib EQU 0x21 STATUS_temp EQU 0x70 W_temp EQU 0x71 org 0x0000 GOTO inic org 0x0004 GOTO interr inic
;inicia con un reset ;vector de interrupción ;salta a la rutina de atención a la interrupción
CALL initrans ;inicializa puerto serie como transmisor BSF STATUS,RP0 ;Banco1 BSF TRISC,2 ;patita RC2/CCP1 como entrada BCF STATUS,RP0 ;Banco 0 MOVLW 0x01 MOVWF T1CON ;Configura Timer1 modo temporizador, preesc 1/1 CLRF TMR1H ;Inicializa en cero el timer 1 CLRF TMR1L ;apaga el módulo CCP para inicializar CLRF CCP1CON ;limpia latch de CCP1 BSF CCP1CON,CCP1M2 CCP1CON,CCP1M2 ;Habilita modulo CCP1 para modo de captura BSF CCP1CON,CCP1M0 CCP1CON,CCP1M0 ;en transición de subida BCF PIR1,CCP1IF ;limpia bandera de interrupcion. interrupcion. BSF STATUS,RP0 ;banco 1 BSF PIE1,CCP1IE ;Habilita interrupciones del CCP1 BCF STATUS,RP0 ;banco 0 BSF INTCON,PEIE ;Habilita interrupciones de periféricos BSF INTCON,GIE ;Habilita interrupciones globales
;** Programa principal: ;** Lazo infinito main GOTO main
;repite
;***** rutina de atención a la interrupción interr MOVWF W_temp W_temp ;salva contexto SWAPF STATUS,W
13
CLRF STATUS MOVWF STATUS_temp STATUS_temp ;Envío a la PC MOVF CCPR1H,W CCPR1H,W CALL Envbyte MOVF CCPR1L,W CCPR1L,W CALL Envbyte MOVLW 0x0D CALL envia MOVLW 0x0A CALL envia
;copia periodo capturado ;y lo envía por el puerto serie
;envía separador
;Checa bandera CCP1IF y pone TMR1 = 0
BTFSS PIR1,CCP1IF GOTO ret BCF PIR1,CCP1IF CLRF TMR1L CLRF TMR1H ret
;checa bandera de ;si no es bandera ;si es bandera de ;limpia la cuenta
captura de evento de captura retorna captura, la limpia del timer 1
SWAPF STATUS_temp,W ;restablece ;restablece contexto MOVWF STATUS STATUS SWAPF W_temp,F SWAPF W_temp,W RETFIE
;********************** ;********************************** ************************ ************************* ***************** **** ; Subrutina que envía el byte en W por el puerto serie, separado ; en los códigos ASCII de sus dos nibbles hexadecimales hexadecimales ;********************** ;********************************** ************************ ************************* ***************** **** Envbyte: MOVWF msnib ;pone byte en msnib MOVWF lsnib ;y una copia en lsnib SWAPF msnib,1 ;intercambia ;intercambia nibbles en lsnib MOVLW 0x0F ;máscara para limpiar el nibble alto ANDWF msnib,1 msnib,1 ;limpia parte alta de msnib ANDWF lsnib,1 lsnib,1 ;limpia parte alta de lsnib MOVF msnib,W msnib,W ;carga msnib en W CALL asc ;obtiene código ASCII equivalente equivalente CALL envia ;lo envía por el puerto serie MOVF lsnib,W lsnib,W ;carga lsnib en W CALL asc ;obtiene código ASCII equivalente equivalente CALL envia ;lo envía por el puerto serie RETURN asc ADDWF PCL,1 ;Calcula el código a retornar ;Saltando W instrucciones adelante DT "0123456789ABCDEF" ;********************** ;********************************** ************************ ************************* ****************** ***** ;Subrutina ;Subrutina para inicializar el puerto serie USART como transmisor ;a 9600 Bauds, considerando un cristal de reloj de 14.7456 MHZ ;********************** ;********************************** ************************ ************************* ****************** ***** initrans: BCF STATUS,RP1 BSF STATUS,RP0 ;banco 1 BCF TXSTA,BRGH ;pone bit BRGH=0 (velocidad baja) MOVLW 0x17 ;valor para 9600 Bauds (Fosc=14.7456 Mhz) MOVWF SPBRG ;configura 9600 Bauds BCF TXSTA,SYNC ;limpia bit SYNC (modo asíncrono) BSF TXSTA,TXEN ;pone bit TXEN=1 (habilita transmisión) BCF STATUS,RP0 ;regresa al banco 0 BSF RCSTA,SPEN ;pone bit SPEN=1 (habilita puerto serie) RETURN ;********************** ;********************************** ************************ ************************* ***************** **** ;Subrutina ;Subrutina para enviar el byte guardado en W por el puerto serie ;********************** ;********************************** ************************ ************************* ***************** ****
14
envia esp
BSF STATUS,RP0 BTFSS TXSTA,TRMT GOTO esp BCF STATUS,RP0 MOVWF TXREG RETURN end
;banco 1 ;checa si el buffer de transmisión ;si está ocupado espera ;regresa al banco 0 ;envía dato guardado en W
Análisis del código En primer lugar configuramos el registro T1CON, CCP1CON, PIR1, PIE1 e INTCON . Registro T1CON
T1CON=0x01 --0 Bit 7
--0
T1CKPS1 0
T1CKPS0 0
T1OSCEN 0
T1SYNC 0
TMR1CS 0
TMR1ON 1 Bit 0
CCP1M1 0
CCP1M0 1 Bit 0
Divisor de frecuencia del preescaler a 1/1, T1CKPS1=0 T1CKPS0=0 TMR1CS=0, selección de la fuente de reloj a modo temporizador TMR1ON=1, habilitación del Timer1 Registro CCP1CON:
---
---
CCP1X 0
CCP1Y 0
CCP1M3 0
CCP1M2 1
Bit 7
configurado el Módulo CCP1 para modo captura por flanco ascendente en RCy/CCPx, como se muestra en la siguiente figura: CCP1M3=0 CCP1M2=1 CCP1M1=0 CCP1M0=1
Registro PIR1:
Limpia la bandera de interrupción. BCF PIR1,CCP1IF
;limpia bandera de interrupcion. interrupcion.
Registro PIE1:
Habilita interrupciones del CCP1. BSF PIE1,CCP1IE
;Habilita interrupciones del CCP1
15
Registro INTCON:
Habilita interrupciones de periféricos y habilita interrupciones globales. BSF INTCON,PEIE BSF INTCON,GIE
;Habilita interrupciones de periféricos ;Habilita interrupciones globales
Programa principal. principal. Este programa mide el periodo de una señal oscilatoria en la patita RC2/CCP1. El valor de periodo capturado representa el número de ciclos Tcy por periodo y se envía continuamente por el puerto serie. Repitiendo continuamente: main GOTO main
;repite
Subrutina de Interrupción: interr
En primer lugar la rutina de atención a la interrupción interr, salva el contexto (W y STATUS): MOVWF W_temp W_temp SWAPF STATUS,W CLRF STATUS MOVWF STATUS_temp STATUS_temp
;salva contexto
Aquí realiza propiamente las acciones de la subrutina de la interrupción interr. Copia periodo capturado y lo envía por el puerto serie, luego envía el separador 0x0D y 0x0A. 0x0A. A continuación checa bandera de captura de evento; si no es bandera de captura retorna, si es bandera de captura, la limpia, y también limpia la cuenta del timer 1 . BTFSS PIR1,CCP1IF GOTO ret BCF PIR1,CCP1IF CLRF TMR1L CLRF TMR1H
;checa bandera de ;si no es bandera ;si es bandera de ;limpia la cuenta
captura de evento de captura retorna captura, la limpia del timer 1
Por último, la rutina de atención a la interrupción interr reestablece el contexto (W y STATUS): ret
SWAPF MOVWF SWAPF SWAPF
STATUS_temp,W ;restablece ;restablece contexto STATUS STATUS W_temp,F W_temp,W
Subrutinas. Son tres, envbyte, initrans
y envia:
envbyte, subrutina que envía el byte en W por el puerto serie, separado en los códigos ASCII de sus dos nibbles hexadecimales. hexadecimales. initrans, subrutina para inicializar el puerto serie USART como transmisor a 9600 Bauds, considerando considerando un cristal de reloj de 14.7456 MHZ. envia, subrutina para enviar el byte guardado en W por el puerto serie. 16
Ejemplo 2 Ejemplo práctico de control de interrupción Se toma como base de partida el código de la aplicación LED.ASM para realizar un led ( LED1 ) intermitente, en donde este programa programa tiene un ciclo continuo y retardo de software mediante una subrutina Delay. Adicionalmente, presionando una de las teclas SW1 a SW4 ubicadas en los pines RB4 a RB7 respectivamente, respectivamente, se accede temporalmente al LED2 LED2 con la ejecución ejecución del programa principal, encendiéndose inmediatamente y permanece encendido por un tiempo para 3 intermitencias del LED1, sin influenciar de manera evidente la frecuencia intermitente del LED1. El circuito a ser realizado se presenta a continuación:
El código de este ejemplo está disponible en INTRB.ASM y se muestra a continuación: ;************************************************** ; Pic by example ; INTRB.ASM ; ;************************************************** PROCESSOR RADIX INCLUDE
16F877 DEC "P16F877.INC"
;Setup of PIC configuration flags ;XT oscillator ;Disable watch dog timer ;Enable power up timer ;Disable code protect __CONFIG
_XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
17
LED1 LED2 LED3 LED4
EQU EQU EQU EQU
0 1 2 3
Count Count1 nTick
EQU EQU EQU
0x20 0x21 0x22
;Registro utilizado para contar el número de ;intermitencias del LED 1
;Reset Vector ;Punto de inicio del programa al reset de la CPU. ORG
00H
;Salta al cuerpo principal del programa. Puesto que el salto es ;necesario, para evitar toda la parte de código de la gestión de ;la interrupción. goto
Start
;Interrupt vector ;Punto de inicio para toda la subrutina de gestión de la ;interrupción. ORG
04H
;********************************************************************** ; Interrupt handler ;********************************************************************** ;Accede al led 2 para segnalare che c'e' stato un interrupt bsf PORTB,LED2 ;Inicializa el contador de intermitencia del LED1 movlw 3 movwf nTick ;Encera nuevamente el flag RBIF para consentirse la 'interrupt ;de repetirse bcf INTCON,RBIF ;Retorna al programa principal retfie ;********************************************************************** ; Programa principal ;********************************************************************** Start: ;Conmuta al segundo banco de la memoria para acceder a los ;registros TRISA y TRISB bsf
STATUS,RP0
;Definición del puerto B ;La línea de RB0 a RB3 vengono programmate in uscita per ;essere collegate ai quattro led ;Le linee da RB4 a RB7 vengono programmate in ingresso per ;essere collegate ai quattro pulsanti movlw movwf
11110000B TRISB
;Conmuta al primer banco de la memoria bcf
STATUS,RP0
18
;Spegne bcf bcf bcf bcf
tutti i led collegati sulla porta B PORTB,LED1 PORTB,LED2 PORTB,LED3 PORTB,LED4
;Habilita la interrupción del cambio de estado de las líneas ;RB4,5,6,7 movlw 10001000B movwf INTCON ;********************************************************************** ; Loop principal ;********************************************************************** MainLoop call btfss goto goto
Delay
;Retardo de software
PORTB,LED1 TurnOnLed1 TurnOffLed1
;Led acceso ? ;No, lo accende ;Si, lo spegne
;Accensione led e decremento del contatore di lampeggi TurnOnLed1 bsf
PORTB,LED1
;Controlla se LED 2 di segnalazione dell'interrupt e' gia ;acceso. ;Se e' acceso decrementa el contador nTick ad ogni lampeggio ;di LED1. Quando nTick vale 0 spegne LED 2 btfss goto
PORTB,LED2 MainLoop
;LED2 acceso ? ;No, continua a lampeggiare
decf btfss goto
nTick,1 STATUS,Z MainLoop
;Se, decrementa nTick ;nTick = 0 ? ;No, continua a lampeggiare
bcf
PORTB,LED2
;Se, apaga LED2
MainLoop
;Continua a lampeggiare
goto
;Spegnimento led TurnOffLed1 bcf goto
PORTB,LED1 MainLoop
;Spegne LED 1 ;Continua a lampeggiare
;********************************************************************** ; Subroutine ;********************************************************************** ;Subroutine de retardo de software Delay clrf clrf
Count Count1
DelayLoop decfsz
Count,1
19
goto
DelayLoop
decfsz goto
Count1,1 DelayLoop
return END
El acceso al LED 2 en correspondencia al presionar una tecla es li geramente retardado, en cuanto a la lectura de estado de la línea RB4-RB7 no será efectuada por el hardware de control de interrupción del programa programa principal a cada ciclo del lazo. El rápido retardo es devuelto devuelto por la presencia de la subrutina Delay dentro del lazo principal.
Análisis del código INTRB.ASM Se parte de la dirección ORG 00H que sirve para posicionar el programa a partir del vector reset, que es la localización 0. La primera instrucción que el PIC encuentra es un desvío incondicionado incondicionado para la etiqueta Start: ORG goto
00H Start
seguido de una nueva dirección: ORG
04H
Que se entra al código de una subrutina de control de interrupción: bsf
PORTB,LED2
movlw movwf
3 nTick
bcf
INTCON,RBIF
retfie
Como una interrupción de control se localiza localiza necesariamente necesariamente a partir de la dirección 04H, para evitar que siga ejecutando esta posición se debe terminar con una instrucción de salto incondicional. El código de control de interrupción, en este caso, es muy simple y se limita a encender el LED2, que encera el registro existente nTick con el número de intermitencias hasta llegar al LED2, deberá apagarse y encerar el flag RBIF para permitir al circuito la generación de una nueva interrupción. La instrucción RETFIE permite al PIC retornar al programa principal que fue interrumpido por la interrupción y activar la máscara GIE para permitir una nueva interrupción.
1. Generación de la interrupción cuando se presiona una tecla cualquiera Las instrucciones que configuran el registro INTCON son las siguientes: movlw movwf
10001000B INTCON
20
donde se coloca en uno el bit GIE ( bit 7 ) que es la habilitación global de las interrupciones y también se pone en uno el bit RBIF ( bit 3 ) que habilita la interrupción sobre la variación de estado de la línea RB4-RB7. En la práctica, habiendo habiendo conectado conectado como llaves SW1, SW2, SW3 e SW4 sobre la línea línea de I/O RB4, RB5, RB6 y RB7 , con la presión de cualquiera cualquiera de las teclas se produce una variación variación de estado que genera una interrupción.
2. El programa principal Realiza la operación de encender y apagar el LED1, y en cada encendido encendid o de LED1 decrementa el contador nTich hasta llegar a cero; en correspondencia con esto será apagado el LED2.
Ejemplo 3 Ejemplo práctico de control de varias interrupciones Para controlar varias interrupciones simultáneamente se utiliza el siguiente circuito, en donde las interrupciones a ser controladas son: la interrupción sobre la cuenta del registro TMR0 y la interrupción al cambio cambio de nivel de las líneas RB4 a RB7. La aplicación establece la ejecución de las tres siguientes tareas a una velocidad tal que se asemeja con una ejecución paralela: paralela: •
•
•
El LED1 es intermitente con la frecuencia de retardo de software mediante una subrutina Delay, El LED2 se prende por tres ciclos del LED1 cuando se presiona una tecla cualquiera de las líneas RB4 a RB7. El LED3 es intermitente a una frecuencia correspondiente a la frecuencias de oscilación del cristal 4MHz dividido para 4 y una relación 1:256, el tiempo de prendido y apagado se establece con la cuenta de TMR0 hasta producirse overflow.
El circuito a ser realizado se presenta a continuación:
21
El código de este ejemplo está disponible en DBLINT.ASM y se muestra a continuación: ;************************************************** ; Pic by example ; DBLINT.ASM ; ;************************************************** PROCESSOR RADIX INCLUDE
16F877 DEC "P16F877.INC"
;Setup of PIC configuration flags ;XT oscillator ;Disable watch dog timer ;Enable power up timer ;Disable code protect __CONFIG LED1 LED2 LED3 LED4
EQU EQU EQU EQU
0 1 2 3
Count Count1 nTick
EQU EQU EQU
0x20 0x21 0x22
_XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
;Reset Vector ;Starting point at CPU reset ORG
00H
;Jump to the main body of program to avoid the interrupt ;handler ;code.
22
goto
Start
;Interrupt vector ;Starting point at CPU interrupts ORG
04H
;********************************************************************** ; Interrupt handler ;********************************************************************** ;Check the interrupt event btfsc goto btfsc goto
INTCON,T0IF IntT0IF INTCON,RBIF IntRBIF
;********************************************************************** ; TMR0 Interrupt handler ;********************************************************************** IntT0IF ;Turn on LED3 if it's off btfsc goto bsf goto LED3_off bcf goto
PORTB,LED3 LED3_off PORTB,LED3 End_ih PORTB,LED3 End_ih
;********************************************************************** ; RB4-RB7 interrupt handler ;********************************************************************** IntRBIF ;Turn on LED 2 bsf
PORTB,LED2
;Starts the LED1 blink counter movlw movwf goto
3 nTick End_ih
;********************************************************************** ;Reset the T0IF and RBIF flags to re-enable the interrupts End_ih bcf bcf
INTCON,T0IF INTCON,RBIF
;Go back to the main program retfie
;********************************************************************** ; Main body ;********************************************************************** Start: ;Conmuta al segundo banco de la memoria para acceder al ;registro TRISB
23
bsf
STATUS,RP0
;Definición del puerto B ;Definición de la línea de I/O (0=Salida, 1=Ingreso) ;Le linee da RB0 a RB3 vengono programmate in uscita per ;essere collegate ai quattro led Le linee da RB4 a RB7 vengono ;programmate in ingresso per essere collegate ai quattro ;pulsanti movlw movwf
11110000B TRISB
;Assegna il PRESCALER a TMR0 e lo configura a 1:256 movlw movwf
00000111B OPTION_REG
;Commuta sul primo banco dei registri bcf
STATUS,RP0
;Spegne bcf bcf bcf bcf
tutti i led collegati sulla porta B PORTB,LED1 PORTB,LED2 PORTB,LED3 PORTB,LED4
;Abilita l'interrupt sul TMR0 e sul cambiamento di stato delle ;linee RB4,5,6,7 movlw movwf
10101000B INTCON
;********************************************************************** ; Loop principale ;********************************************************************** MainLoop call btfss goto goto
Delay
;Ritardo software
PORTB,LED1 TurnOnLed1 TurnOffLed1
;Led acceso ? ;No, lo accende ;Si, lo spegne
;Accensione led e decremento del contatore di lampeggi TurnOnLed1 bsf
PORTB,LED1
;Controlla se LED 2 di segnalazione dell'interrupt e' gia ;acceso. ;Se e' acceso decrementa il contatore nTick ad ogni lampeggio ;di LED1. Quando nTick vale 0 spegne LED 2 btfss goto
PORTB,LED2 MainLoop
;LED2 acceso ? ;No, continua a lampeggiare
decf btfss goto
nTick,1 STATUS,Z MainLoop
;Si, decrementa nTick ;nTick = 0 ? ;No, continua a lampeggiare
bcf
PORTB,LED2
;Si, spegne LED2
MainLoop
;Continua a lampeggiare
goto
24
;Spegnimento led TurnOffLed1 bcf goto
PORTB,LED1 MainLoop
;Spegne LED 1 ;Continua a lampeggiare
;********************************************************************** ; Subroutine ;********************************************************************** ;Subroutine di ritardo software Delay clrf clrf
Count Count1
DelayLoop decfsz goto
Count,1 DelayLoop
decfsz goto
Count1,1 DelayLoop
return END
Análisis del código DBLINT.ASM El control de interrupción verifica el evento generado por una interrupción, por lo cual, se debe realizar una verificación para determinar qué evento fue generado, esto se obtiene con las siguientes instrucciones: btfsc goto btfsc goto
INTCON,T0IF IntT0IF INTCON,RBIF IntRBIF
en donde los flags T0IF y RBIF serán controlados para ver si el evento que provoca la interrupción proviene del registro TMR0 o del puerto RB4-RB7 respectivamente, y luego será puesta en ejecución la subrutina de control a partir de las etiquetas intT0IF e intRBIF. Además, antes de devolver el control al programa principal se debe encerar los flag T0IF y RBIF, para asegurar que el próximo evento pueda generar interrupción.
25