7 manejo de interrupciones pic
DESCRIPTION
Manejo de Interrupciones PICTRANSCRIPT
1
Manejo de Interrupciones
2
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 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.
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á 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 con independencia de cómo se 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 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 bits individuales.
Al atender una interrupción, el bit GIE se borra automáticamente con lo que se deshabilita la
posibilidad de futuras interrupciones, la dirección de retorno se envía al Stack y el Contador de
Programa se carga con la dirección 0004 hex. (vector de interrupción). En esta dirección
comenzará la subrutina de 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 bits 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á la solicitud de interrupción correspondiente, pero si está activada
3
(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.
7.2. Tipos de Eventos y Bits de Habilitación
En el registro INTCON sólo se encuentran tres controles de interrupciones:
1. Un cambio de estado sobre la línea RB0 ( pin de interrupció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 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á se elige con el bit INTEDG
(OPTION_REG<6>). Cuando este bit se pone a uno, la interrupción tendrá lugar en la
transición de cero a uno, por el contrario, el flanco de bajada ocasionará la interrupción
cuando el bit se coloque a 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. Si están habilitadas y el microcontrolador se encuentra en 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 que se produzca
4
en las patillas RB7:RB4 también la ocasionará, para habilitarla, hay que poner a uno el
flag de interrupciones RBIE (INTCON<3>). Cualquier cambio de 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, antes de habilitar esta 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) y PIE1, PIE2 (Mascaras).
Una interrupción de cualquiera de estos eventos puede ser conseguida habilitando o
deshabilitando independientemente los siguientes bits de los registro INTCON, PIR1 y, PIR2:
• INTE. Si este bit está en 1 habilitará la interrupción de cambio de estado sobre la línea
RB0
• T0IE. Si este bit está en 1 habilitará la interrupción de final de conteo del registro
TMR0
• RBIE. Si este bit está en 1 habilitará la interrupción de cambio de estado sobre una de
las líneas de RB4 a RB7
• EEIE. Si este bit está en 1 habilitará la interrupción 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 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 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 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,
5
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 en la dirección de memoria 0004H,
denominada Interrupt Vector ( vector de interrupción ). Por lo 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. Descripción Registro
INTF Externa. Se coloca en 1 cuando la interrupción INT ocurre, es decir cuando
cambia de estado la línea RB0. 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 TMR0 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 Recepción USAR. PIR1
TXIF Transmisión USAR. PIR1
SSPIF Puerto Serie Síncrono. PIR1
CCP1IF Capturador/Comparador 1. 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
6
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:
• El bit GIE está activado (en alto)
• El bit PEIE está activado (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 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 instrucción a ejecutar es guardada en el stack.
• Ejecuta un salto a la localidad de programa 0004h denominada vector de
interrupción, en donde el usuario deberá haber colocado el inicio de la rutina de
atención a la 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 mostrado en la siguiente figura. En este diagrama se muestran las 14
fuentes de interrupción de los 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.
7
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 se realice en la 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 de servicio de interrupciones. Si esto fuera así, se deberán 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, se deberán recuperar para que queden en su estado original. Un
ejemplo para salvar los registros de estado, W y PCLATH en memoria puede ser el siguiente:
8
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
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 ;Salva STATUS en STATUS_temp (Banco 0)
; MOVF PCLATH,W ;sólo se requiere si se están usando las páginas 1,2,y/o 3
; MOVWF 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 ;rescata PCLATH
; MOVWF PCLATH ;si se usan las paginas 1,2 y/o 3
SWAPF STATUS_temp,W ;rescata el STATUS original
MOVWF STATUS ;restablece banco original
SWAPF W_temp,F ;rescata el W original
SWAPF W_temp,W ;sin alterar el STATUS ya rescatado.
RETFIE
El programa está dividido en dos partes, la primera 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. La instrucción RETFIE llevará el flujo del programa a la dirección 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 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-x
GIE PEIE T0IE INTE RBIE T0IF INTF RBIF
Bit 7 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
9
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 cambio de nivel en PORTB
1= Se ha producido un cambio de nivel en los pines RB7:RB4. Se borra por software.
0= No se ha producido un cambio de nivel en los pines RB7: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 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-x
PSPIF ADIF RCIF TXIF SSPIF CCP1IF TMR2IF TMR1IF
Bit 7 Bit 0
bit 7: 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. 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
10
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. Las 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 R/W-0 U-0 R/W-0 R/W-0 U-0 U-0 R/W-x
--- (1) --- EEIF BCLIF --- --- CCP2IF
Bit 7 Bit 0
bit 7: No implementado: se lee como “0”
bit 6: Reservado: Mantiene este bit siempre a cero
11
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 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0
PSPIE(1)
ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE
Bit 7 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.
12
1 = Habilita la interrupción de 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 contiene los bits individuales que habilita las interrupciones del periférico
CCP2, la interrupción por colisión del SSP y la interrupción de escritura en la EEPROM.
U-0 R/W-0 U-0 R/W-0 R/W-0 U-0 U-0 R/W-0
--- 0 --- EEIE BCLIE -- -- CCP2IE
Bit 7 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 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 por colisión en el bus SSP.
bit 2-1 No implementados, se leen como “0”
13
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 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 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 ;inicia con un reset
GOTO inic
org 0x0004 ;vector de interrupción
GOTO interr ;salta a la rutina de atención a la interrupción
inic 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 ;Habilita modulo CCP1 para modo de captura
BSF CCP1CON,CCP1M0 ;en transición de subida
BCF PIR1,CCP1IF ;limpia bandera de 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 ;salva contexto
SWAPF STATUS,W
14
CLRF STATUS
MOVWF STATUS_temp
;Envío a la PC
MOVF CCPR1H,W ;copia periodo capturado
CALL Envbyte ;y lo envía por el puerto serie
MOVF CCPR1L,W
CALL Envbyte
MOVLW 0x0D ;envía separador CALL envia
MOVLW 0x0A
CALL envia
;Checa bandera CCP1IF y pone TMR1 = 0
BTFSS PIR1,CCP1IF ;checa bandera de captura de evento
GOTO ret ;si no es bandera de captura retorna
BCF PIR1,CCP1IF ;si es bandera de captura, la limpia
CLRF TMR1L ;limpia la cuenta del timer 1
CLRF TMR1H
ret SWAPF STATUS_temp,W ;restablece contexto
MOVWF 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
;***************************************************************
Envbyte:
MOVWF msnib ;pone byte en msnib
MOVWF lsnib ;y una copia en lsnib
SWAPF msnib,1 ;intercambia nibbles en lsnib
MOVLW 0x0F ;máscara para limpiar el nibble alto ANDWF msnib,1 ;limpia parte alta de msnib
ANDWF lsnib,1 ;limpia parte alta de lsnib
MOVF msnib,W ;carga msnib en W
CALL asc ;obtiene código ASCII equivalente
CALL envia ;lo envía por el puerto serie
MOVF lsnib,W ;carga lsnib en W
CALL asc ;obtiene código ASCII 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 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 para enviar el byte guardado en W por el puerto serie
;***************************************************************
15
envia BSF STATUS,RP0 ;banco 1
esp BTFSS TXSTA,TRMT ;checa si el buffer de transmisión
GOTO esp ;si está ocupado espera
BCF STATUS,RP0 ;regresa al banco 0
MOVWF TXREG ;envía dato guardado en W
RETURN
end
Análisis del código
En primer lugar configuramos el registro T1CON, CCP1CON, PIR1, PIE1 e INTCON.
Registro T1CON
T1CON=0x01
--- --- T1CKPS1 T1CKPS0 T1OSCEN T1SYNC TMR1CS TMR1ON
0 0 0 0 0 0 0 1
Bit 7 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 CCP1Y CCP1M3 CCP1M2 CCP1M1 CCP1M0
0 0 0 1 0 1
Bit 7 Bit 0
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.
Registro PIE1:
Habilita interrupciones del CCP1.
BSF PIE1,CCP1IE ;Habilita interrupciones del CCP1
16
Registro INTCON:
Habilita interrupciones de periféricos y habilita interrupciones globales.
BSF INTCON,PEIE ;Habilita interrupciones de periféricos
BSF INTCON,GIE ;Habilita interrupciones globales
Programa 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 ;salva contexto
SWAPF STATUS,W
CLRF STATUS
MOVWF STATUS_temp
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.
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 ;checa bandera de captura de evento
GOTO ret ;si no es bandera de captura retorna
BCF PIR1,CCP1IF ;si es bandera de captura, la limpia
CLRF TMR1L ;limpia la cuenta del timer 1
CLRF TMR1H
Por último, la rutina de atención a la interrupción interr reestablece el contexto (W y STATUS):
ret SWAPF STATUS_temp,W ;restablece contexto
MOVWF STATUS
SWAPF W_temp,F SWAPF 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.
initrans, subrutina para inicializar el puerto serie USART como transmisor a 9600 Bauds,
considerando un cristal de reloj de 14.7456 MHZ.
envia, subrutina para enviar el byte guardado en W por el puerto serie.
17
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 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, se accede temporalmente al LED2 con la 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 16F877
RADIX DEC
INCLUDE "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
18
LED1 EQU 0
LED2 EQU 1
LED3 EQU 2
LED4 EQU 3
Count EQU 0x20
Count1 EQU 0x21
nTick EQU 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 11110000B
movwf TRISB
;Conmuta al primer banco de la memoria
bcf STATUS,RP0
19
;Spegne tutti i led collegati sulla porta B
bcf PORTB,LED1
bcf PORTB,LED2
bcf PORTB,LED3
bcf 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 Delay ;Retardo de software
btfss PORTB,LED1 ;Led acceso ?
goto TurnOnLed1 ;No, lo accende
goto TurnOffLed1 ;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 PORTB,LED2 ;LED2 acceso ? goto MainLoop ;No, continua a lampeggiare
decf nTick,1 ;Se, decrementa nTick
btfss STATUS,Z ;nTick = 0 ?
goto MainLoop ;No, continua a lampeggiare
bcf PORTB,LED2 ;Se, apaga LED2
goto MainLoop ;Continua a lampeggiare
;Spegnimento led
TurnOffLed1
bcf PORTB,LED1 ;Spegne LED 1
goto MainLoop ;Continua a lampeggiare
;**********************************************************************
; Subroutine
;**********************************************************************
;Subroutine de retardo de software
Delay
clrf Count
clrf Count1
DelayLoop
decfsz Count,1
20
goto DelayLoop
decfsz Count1,1
goto DelayLoop
return
END
El acceso al LED 2 en correspondencia al presionar una tecla es ligeramente 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 principal a cada ciclo del lazo. El rápido retardo es 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 para la etiqueta Start:
ORG 00H
goto 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 3
movwf nTick
bcf INTCON,RBIF
retfie
Como una interrupción de control se localiza 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 10001000B
movwf INTCON
21
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 conectado como llaves SW1, SW2, SW3 e SW4 sobre la línea de I/O
RB4, RB5, RB6 y RB7 , con la presión de cualquiera de las teclas se produce una 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 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 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:
• 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:
22
El código de este ejemplo está disponible en DBLINT.ASM y se muestra a continuación:
;**************************************************
; Pic by example
; DBLINT.ASM
;
;**************************************************
PROCESSOR 16F877
RADIX DEC INCLUDE "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
LED1 EQU 0
LED2 EQU 1
LED3 EQU 2
LED4 EQU 3
Count EQU 0x20
Count1 EQU 0x21
nTick EQU 0x22
;Reset Vector
;Starting point at CPU reset
ORG 00H
;Jump to the main body of program to avoid the interrupt ;handler
;code.
23
goto Start
;Interrupt vector
;Starting point at CPU interrupts
ORG 04H
;**********************************************************************
; Interrupt handler ;**********************************************************************
;Check the interrupt event
btfsc INTCON,T0IF
goto IntT0IF
btfsc INTCON,RBIF
goto IntRBIF
;**********************************************************************
; TMR0 Interrupt handler
;**********************************************************************
IntT0IF
;Turn on LED3 if it's off
btfsc PORTB,LED3
goto LED3_off
bsf PORTB,LED3
goto End_ih
LED3_off
bcf PORTB,LED3
goto End_ih
;********************************************************************** ; RB4-RB7 interrupt handler
;**********************************************************************
IntRBIF
;Turn on LED 2
bsf PORTB,LED2
;Starts the LED1 blink counter
movlw 3
movwf nTick
goto End_ih
;**********************************************************************
;Reset the T0IF and RBIF flags to re-enable the interrupts
End_ih
bcf INTCON,T0IF
bcf INTCON,RBIF
;Go back to the main program
retfie
;**********************************************************************
; Main body
;**********************************************************************
Start:
;Conmuta al segundo banco de la memoria para acceder al
;registro TRISB
24
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 11110000B
movwf TRISB
;Assegna il PRESCALER a TMR0 e lo configura a 1:256
movlw 00000111B
movwf OPTION_REG
;Commuta sul primo banco dei registri
bcf STATUS,RP0
;Spegne tutti i led collegati sulla porta B
bcf PORTB,LED1
bcf PORTB,LED2
bcf PORTB,LED3
bcf PORTB,LED4
;Abilita l'interrupt sul TMR0 e sul cambiamento di stato delle
;linee RB4,5,6,7
movlw 10101000B
movwf INTCON
;********************************************************************** ; Loop principale
;**********************************************************************
MainLoop
call Delay ;Ritardo software
btfss PORTB,LED1 ;Led acceso ?
goto TurnOnLed1 ;No, lo accende
goto TurnOffLed1 ;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 PORTB,LED2 ;LED2 acceso ?
goto MainLoop ;No, continua a lampeggiare
decf nTick,1 ;Si, decrementa nTick btfss STATUS,Z ;nTick = 0 ?
goto MainLoop ;No, continua a lampeggiare
bcf PORTB,LED2 ;Si, spegne LED2
goto MainLoop ;Continua a lampeggiare
25
;Spegnimento led
TurnOffLed1
bcf PORTB,LED1 ;Spegne LED 1
goto MainLoop ;Continua a lampeggiare
;**********************************************************************
; Subroutine
;**********************************************************************
;Subroutine di ritardo software
Delay
clrf Count
clrf Count1
DelayLoop
decfsz Count,1
goto DelayLoop
decfsz Count1,1
goto 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 INTCON,T0IF
goto IntT0IF
btfsc INTCON,RBIF goto 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.