Sunteți pe pagina 1din 17

Interrupciones en Microcontroladores PIC

Fuentes de interrupción y registros asociados

Las interrupciones en los microcontroladores PIC de gama media son enmascarables y fijas.
Esto significa que las interrupciones se pueden habilitar o deshabilitar a nivel global, así como cada
fuente de interrupción se puede activar o desactivar individualmente, como se muestra en la Figura
7.7. Para que una solicitud de interrupción sea atendida, tanto la fuente de interrupción como el
sistema en su conjunto (interrupción global) deben estar habilitados.
El sistema se habilita o inhabilita globalmente mediante el bit GIE (global interrupt enable) del
registro especial de función INTCON
Los dispositivos que pueden generar solicitudes de interrupción son habilitados o deshabilitados
por bits en los registros INTCON, PIE1 y PIE2.

Debido a las interrupciones fijas, cuando una interrupción es atendida, el microcontrolador


ejecuta la instrucción almacenada en la dirección 4 de la memoria del programa.
Al escribir la subrutina de servicio de interrupción, el programador debe
encontrar la fuente que pidió la interrupción. Esto se hace mediante la lectura
de los bits apropiados en los registros de funciones especiales (INTCON, PIR1, y
PIR2) asociados con el sistema de interrupción en el PIC.

Cuando se solicita una interrupción (suponiendo que el sistema global y la fuente especifica de
interrupción están habilitados), el microcontrolador termina de ejecutar la instrucción actual,
almacena el contador de programa en la pila, y salta a la dirección 4 en la memoria del programa.
El tiempo transcurrido entre el momento en que la interrupción es solicitada y la ejecución de la
primera instrucción en la “subrutina de servicio de interrupción” localizada en el rango 4 de
direcciones es de 3 a 3.75 ciclos de la máquina. Este tiempo es llamado “tiempo de latencia”.
El tiempo de latencia exacto depende del momento específico dentro del ciclo de máquina en el
que la interrupción es solicitada y si la solicitud es interna o externa. La Figura 7.5 ilustra
las operaciones llevadas a cabo por el microcontrolador en el tiempo de latencia. En primer lugar,
debe terminar con la instrucción que estaba siendo ejecutada cuando la interrupción fue solicitada.
Entonces, el valor del contador de programa (PC) apuntando a la siguiente instrucción se almacena
en la pila. Por último, el microcontrolador establece el PC en la dirección 0004, haciendo el salto
del programa a la ejecución de la primera dirección del “programa de servicio de interrupción”.
Cuando una solicitud de interrupción está siendo atendida, el sistema de interrupción global está
desactivado (GIE bit con valor 0).

Cada módulo E/S puede generar por lo menos una solicitud de interrupción. Las posibles
fuentes de interrupción son:

• Interrupción externa en pin INT del microcontrolador


• Interrupción debido a un cambio en la lógica de Estado entradas RB4: RB7 en el puerto B
• Interrupción debido al desbordamiento de Timer0, Timer1, o Timer2
• Interrupción debido a un evento en el módulo de CCP (Capture, Compare and Pulse Width
Modulation)
• Interrupción en el puerto serie USART
• Interrupción debida al conversor A/D
Figura 7.5
Operaciones del microcontrolador durante el tiempo de latencia: la instrucción actual está terminada, el valor
del PC se almacena en la pila, y el PC se carga con 0004, haciendo que se ejecute la primera instrucción en
la subrutina de servicio de interrupción. Cuando se ejecuta esta subrutina, el sistema de interrupción esta
deshabilitado. La instrucción retfie, utilizada para volver al programa interrumpido, activa nuevamente el
sistema de interrupción.

Todos los microcontroladores PIC de gama media usan al menos un registro especial de función
para el control de las interrupciones: el registro INTCON. Este registro controla las interrupciones
externas (de pin INT), la interrupción debido a cambios en pines RB4 a RB7, y la interrupción por
desbordamiento TIMER0. También esta el bit (GIE) para habilitar globalmente las interrupciones.
Las restantes fuentes de interrupción son controladas con los registros PIE1, PIR1, PIE2 y PIR2.
Figura 7.6 muestra el bit GIE en el registro de control de interrupción INTCON.

La descripción de cada bit es:

GIE (habilitación global de interrupción). Este bit activa (GIE = 1) o desactiva


(GIE = 0) el sistema global de interrupciones del microcontrolador.

Cuando una interrupción es solicitada, este bit se ajusta automáticamente a 0. Por lo tanto,
los sistemas de interrupción se desactivaran hasta que GIE = 1. El retorno de instrucción al final de
la subrutina de servicio de interrupción (retfie) establece el bit GIE a 1, lo que activa nuevamente el
sistema global de interrupción en el PIC. En un reset, el bit GIE se establece a 0, desactivando el
sistema de interrupción.

PEIE (habilitación de interrupción periférica). Este bit habilita las fuentes de interrupción
no presentes en el registro INTCON, pero presentes en los registros PIE.
T0IE, T0IF. Estos bits están relacionados con la interrupción de Timer0. Cuando
T0IE = 1, la interrupción de Timer0 está habilitada. T0IF indica desbordamiento
del Timer0. Cuando este bit se pone a 1 se genera una solicitud de interrupción si T0IE = 1.
INTE, INTF. Estos bits están relacionados con la interrupción externa. El bit INTE
habilita esta interrupción. El bit INTF es una bandera que indica la detección de un flanco
(elevación o descenso) en el pin INT de entrada.
RBIE, RBIF. Estos bits están relacionados con la interrupción debida a un cambio
del nivel en los bits RB4 a RB7. RBIE = 1 habilita esta interrupción. RBIF es una bandera que
indica un cambio en uno de los pines RB4 a RB7. Si RBIE = 1, se produce una interrupción.

Figura 7.7
Papel de los bits en el registro INTCON en el sistema de interrupción para microcontroladores PIC de gama
media. El sistema se activa o desactiva con el bit GIE. Cada fuente de interrupción tiene un bit de control que
activa o desactiva la petición de interrupción. Las peticiones de interrupción se muestran en las banderas
T0IF, INTF y RBIF independientemente de su orden de llegada al CPU.

Figura 7.7 ilustra el funcionamiento de bits en el registro INTCON. La petición de la interrupción


externa se realiza a través del pin INT. Este pin funciona en el pin RB0 del puerto B en la mayoría
de los microcontroladores PIC de gama media. Esta interrupción se produce por un flanco de la
señal conectada al pin INT.

El bit INTEDG en el registro OPTION (bit OPTION<6>) selecciona un flanco ascendente o


descendente. La interrupción externa está marcada por el bit INTF en el registro INTCON, y se
activa o desactiva con el bit INTE en este mismo registro.

Si los pines RB4 a RB7 han sido programados como entradas y hay un cambio de nivel en la lógica
de las señales en cualquiera de estas entradas, se generara una solicitud de interrupción. En este
caso, el bit RBIF en el registro INTCON se establece en 1. Esta interrupción puede ser activada o
desactivada con el bit RBIE del mismo registro.
Esta interrupción puede ser utilizada para despertar al microcontrolador cuando se encuentra en
modo de bajo consumo (sleep mode).

Figura 7.8 muestra un circuito simplificado utilizado para generar la interrupción por un cambio de
nivel en cualquiera de las entradas RB4 a RB7. La señal en el pin es muestreada dos veces en dos
intervalos de tiempo diferentes en función de Q1 y Q3 en el ciclo de la máquina (Figura 2.2). Si el
nivel lógico de la señal en el pin ha cambiado en el tiempo de muestreo, la salida Q para el D será
diferente, haciendo que la salida de la puerta XOR sea igual a 1. Esto establece el bit RBIF a 1, por
lo tanto genera una solicitud de interrupción. Para que este proceso tenga lugar, los pines deben
estar configurados como pines de entrada, es decir, bit TRISB<i> = 1.
Los registros PIE y PIR controlan la interrupción de los distintos módulos periféricos en el
microcontrolador PIC. El registro PIE (PIE1, PIE2) contiene los bits para habilitar o deshabilitar las
interrupciones de periféricos. El registro PIR (PIR1, PIR2) contiene los bits que indican que una
interrupción ha sido solicitada por los distintos periféricos. La estructura de estos registros,
es decir, el significado de los bits y su posición dentro de un registro, cambia de un PIC a otro.

Figura 7.8
Circuito simplificado asociado a los pines RB4 a RB7 programados como entradas. La figura ilustra la
generación de interrupciones debido a cambios en el nivel lógico de las entradas. Q1 y Q3 son señales
internas correspondientes a estados de igual nombre en un ciclo de máquina
(Vea la Figura 2.2).

Ejemplo 7.2
Registros PIE y PIR en el PIC16F87x. La estructura y composición de los registros PIE y PIR
dependerá del modelo de PIC utilizado debido a que la disposición de Módulos I/O también
dependen de cada dispositivo. La familia de microcontroladores PIC16F87x tiene dos registros PIE
(PIE1 y PIE2) y dos registros PIR (PIR1 y PIR2). Su estructura se muestra en la Figura 7.9. La
Tabla 7.2 muestra el nombre de los bits y los módulos E/S asociados con ellos.
Para que una solicitud de interrupción realmente interrumpa el programa en ejecución, primero es
necesario que el sistema de interrupción en el PIC este habilitado.
Esto significa que el bit GIE en el registro INTCON debe ser 1. En segundo lugar, es necesario que
el origen de la interrupción este también habilitado. Por ejemplo, en el caso de una interrupción
externa, el bit INTE en el registro INTCON debe ser 1.
En estas condiciones, la solicitud tendrá éxito. Durante la ejecución de la interrupción el bit GIE es
puesto automáticamente en 0, deshabilitando las interrupciones. Por lo tanto, nuevas
interrupciones no recibirán servicio. El sistema de interrupción global será nuevamente habilitado
cuando el microcontrolador ejecute la instrucción retfie para volver al programa que se había
interrumpido. La instrucción retfie restablece el bit GIE en 1, lo que habilita nuevamente el sistema
global de interrupciones. Esto deja al microcontrolador PIC listo para atender nuevas solicitudes de
interrupción.

Cuando se produce un reset, el bit GIE se establece en 0, por lo tanto el microcontrolador no


atenderá cualquier solicitud de interrupción después de un reset. Por ejemplo, cuando el
microcontrolador se enciende por primera vez, comienza a trabajar con el sistema de interrupción
deshabilitado. El programador tiene que habilitar las interrupciones mediante el ajuste del bit GIE a
1.
Los bits que controlan las interrupciones individuales (T0IE, INTE, etc) no se modifican cuando se
solicita una interrupción. Las banderas de interrupción individuales (T0IF, INTF, etc) se establecen
automáticamente en 1 para informar sobre la solicitud de interrupción. Ellos se pueden setear
nuevamente a 0 por el programa que atiende la solicitud de interrupción.

Subrutina de Servicio de Interrupción - Estructura

Las interrupciones son eventos que pueden ocurrir en cualquier momento durante la ejecución de
una instrucción. No es posible predecir que instrucción se estará ejecutando cuando llegue una
solicitud de interrupción del CPU. Esta situación obliga al programador a tomar precauciones para
mantener la integridad de los registros que se usan en el programa interrumpido y el programa que
atiende a la interrupción. Los registros más utilizados son el W y el STATUS.
Por lo tanto, sus valores, cuando la interrupción es solicitada deben ser almacenados en la
memoria, y una vez que la subrutina de servicio de interrupción ha terminado, estos valores deben
ser restaurados para continuar con la ejecución del programa.
En la mayoría de los microprocesadores y microcontroladores, los valores de los registros se
almacenan en la pila. Esto se hace usando instrucciones de cómo PUSH registro para almacenar
un registro en la pila y POP registro para recuperar los valores. La estructura de pila LIFO permite
anidar varias subrutinas de servicio de interrupción. Por lo tanto, el subprograma de servicio de
interrupción puede ser interrumpido por un segundo programa, aunque el primero no haya
terminado todavía. Esto logra sistemas de interrupción muy complejos y de gran alcance.
Los microcontroladores PIC de gama media no tienen instrucciones como PUSH o POP, y la pila
sólo puede almacenar el contador de programa. La ausencia de una pila para almacenar el
contenido de los registros, mientras que una interrupción está siendo atendida hace que sea muy
difícil anidar subrutinas de servicio de interrupción. Por lo tanto, el sistema de interrupción en este
tipo de microcontrolador es relativamente simple. Si el microcontrolador esta atendiendo una
solicitud de servicio de interrupción y recibe otra solicitud de interrupción, la nueva solicitud de
interrupción deberá esperar hasta que la primera haya terminado antes de ser atendida. Esto esta
garantizado intrínsecamente en este tipo de microcontroladores, porque el sistema global de
interrupción se desactiva mientras que el microcontrolador atiende una solicitud de interrupción.

El sistema global de interrupción sólo se activa con la instrucción retfie que termina la subrutina de
servicio de interrupción.
Debido a que la pila sólo puede almacenar el contador de programa, el contenido de los registros
W y STATUS debe ser almacenado en la memoria de datos o en cualquier ubicación disponible.
Esto puede ser una tarea compleja dada la estructura de banco para la memoria de datos y el
hecho de que la mayoría de las instrucciones de transferencia de datos alteran algunos bits en el
registro STATUS. Ejemplo 7.3 ilustra varias soluciones propuesta por el fabricante de
microcontroladores PIC.

Ejemplo 7.3
Recomendaciones para la estructura de un subprograma de solicitud de interrupción. Esta
subrutina utiliza registros TEM_W y TEMP_ST para almacenar el contenido de los registros W y
STATUS. Esta operación parece fácil de llevar a cabo con la siguiente secuencia:

movwf TEMP_W
movf STATUS, W
movwf TEMP_ST

Sin embargo, esta secuencia no es válida porque la instrucción movf afecta el bit Z en el registro
STATUS, por lo que el valor almacenado en el registro TEMP_ST será diferente al estado original
de STATUS. Es necesario el uso de instrucciones que no afecten a los bits del registro STATUS.
Una de ellas es la instrucción swapf.
Utilizando esta instrucción, el segmento del programa se convierte en:

movwf TEMP_W
swapf STATUS, W
movwf TEMP_ST

Esta instrucción almacena el contenido del registro STATUS en el registro TEMP_ST sin alterar el
valor original de los bits. La instrucción, sin embargo, intercambia los nibbles en el registro. Por lo
tanto, los nibbles en TEMP_ST debe ser cambiados antes de abandonar el subprograma de
solicitud de interrupción con el fin de mantener la integridad del registro STATUS. El segmento de
programa que restaura los valores de W y de estado antes de que finalice la subrutina es:

swapf TEMP_ST, W
movwf STATUS
swapf TEMP_W, F
swapf TEMP_W, W

También es necesario tener en cuenta que al menos el registro TEMP_W debe ser localizado en el
banco que estaba activo en el momento de la interrupción. Como no es posible saber de qué banco
se trata, hay varias soluciones en función de si el microcontrolador tiene una zona de memoria
RAM de datos que es común a todos los bancos. Una zona común de memoria de datos es un
área de memoria con el mismo lugar físico en la memoria de datos que puede direccionarse desde
cualquier banco.

Las siguientes son las subrutinas llamadas SRAI1 y SRAI2 con la estructura recomendada por
Microchip para las subrutinas de solicitud de interrupción en función de si el PIC tiene una zona
común para la memoria de datos.
; Este subprograma es para PICs con zona común de memoria RAM, tal como
; PIC16F84:
; Common RAM: Un área de memoria RAM que es la misma en todos los bancos.
; TEMP_W y TEMP_ST se definen en esta zona de memoria common RAM.
;
SRAI1:
movwf TEMP_W ; almacena W en TEMP_W.
swapf STATUS, W ; Intercambia los nibbles de STATUS
movwf TEMP_ST ;y almacena el resultado en TEMP_ST.
;
; Escriba aquí el cuerpo de este subprograma:
;
swapf TEMP_ST, W ; Recupera TEMP_ST e intercambia nibbles
movwf STATUS ; almacena el resultado en STATUS.
swapf TEMP_W, F ; recupera TEMP_W y almacena en
swapf TEMP_W, W ; W sin alterar STATUS.
retfie ; Vuelve al programa interrumpido.
;
;
; Este subprograma es para los PICs sin RAM comunes, tales como PIC16F873.
; Common RAM: Un área de memoria RAM que es el mismo en todos los bancos.
; Registro TEMP_W se define en cualquier banco.
; Registro TEMP_ST definido en el banco 0.
;
SRAI2:
movwf TEMP_W ; almacena W en TEMP_W.
swapf STATUS, W ; intercambia nibbles de STATUS (STATUS sin modificar)
bcf STATUS, RP0 ; selecciona banco 0 (STATUS modificado)
movwf TEMP_ST ; almacena los resultados en TEMP_ST (guarda STATUS sin
;modificar)
;
; Escriba aquí el cuerpo de la subrutina
;
swapf TEMP_ST, W ; Recupera TEMP_ST y almacena en STATUS
movwf STATUS ; intercambiando nibbles. El banco seleccionado
; ahora es el original donde esta TEMP_W.
swapf TEMP_W, F ; recupera TEMP_W y almacena en
swapf TEMP_W, W ; W sin alterar STATUS.
retfie ; retorno de la interrupción.
;

Figura 7.10 ilustra la estructura general de la subrutina de servicio de interrupción en


microcontroladores PIC. Después de preservar el contenido de los registros W y STATUS
siguiendo uno de los procedimientos indicados en el ejemplo 7.3, el programador tiene que
encontrar la fuente que generó la solicitud de interrupción. Una vez que la fuente de interrupción se
ha identificado, puede ser atendida. La identificación de la fuente se puede hacer mediante la
lectura de los diferentes bits indicadores para encontrar cuál tiene el valor 1. Esto es importante
para luego restablecer este bit a 0.
Por último, deben ser restaurados los valores originales en los registros W y STATUS y se debe
volver al programa que fue interrumpido utilizando la instrucción retfie. Esta instrucción habilita el
sistema de interrupción global (setea GIE = 1).
Figura 7.10
Estructura de Subrutina de Servicio de interrupción para microcontroladores PIC de gama media. Con N las
posibles fuentes, las banderas asociadas a estas interrupciones I1, I2, ..., que deben ser consultadas.
Estos indicadores son los bits T0IF, INTF, etc, de los registros INTCON, PIR1, y PIR2.

Los pasos que tienen lugar en la atención de una solicitud de interrupción en microcontroladores
PIC de gama media son:
1. El microcontrolador completa la ejecución de la instrucción actual.
2. El valor del PC se almacena en la pila.
3. El PC se establece en 0004, causando un salto a esta dirección, iniciando la ejecución de la
subrutina de servicio de interrupción.
4. Los valores de los registros W y STATUS se almacenan (véase el ejemplo 7.3).
5. La fuente de interrupción queda determinada chequeando los bits indicadores (flags).
6. Una vez que la fuente ha sido identificada, su bandera se fija a 0.
7. Los valores originales de los registros W y STATUS se restauran (Véase el ejemplo 7.3).
8. Usando la instrucción retfie, el microcontrolador vuelve al programa que se había interrumpido.
Esta instrucción recupera el valor del PC de la pila y habilita nuevamente el sistema de
interrupción global (setea GIE = 1).

Los tres primeros pasos se realizan de forma automática por el microcontrolador, mientras que los
pasos 4 a 8 deben ser implementados en la subrutina de servicio de interrupción.

Ejemplos de solicitudes de interrupción

Reloj de Tiempo Real

Una base de tiempo es un conjunto de variables cuyos valores reflejan el valor de tiempo real en el
microcontrolador. Por ejemplo, una base de tiempo puede consistir en las variables
TICKS, SEGUNDOS, MINUTOS, y HORAS que cuentan décimas de segundos, segundos, minutos
y horas. Estas variables no son más que registros en la memoria de datos del microcontrolador . El
reloj de tiempo real (RTC) es un mecanismo de software basado en interrupciones periódicas para
actualizar la base de tiempo y sincronizar eventos. Por ejemplo, con cada interrupción periódica, el
programa RTC puede incrementar el valor de la variable TICKS, y dependiendo de su valor,
actualizar el resto de variables. Los eventos externos que son sincronizados con la base de
tiempos pueden ser periódicos. Por ejemplo, eventos periódicos pueden ser leer uno de los
canales del convertidor A/D cada 5 segundos o almacenar un valor en el puerto B cada 8
segundos. Ejemplo 7.5 se explica con más detalle cómo se llevan a cabo estas sincronizaciones.

El elemento fundamental en un RTC es la interrupción periódica que actualiza la base de tiempo. El


período T de esta interrupción determina la resolución de tiempo del sistema. Por ejemplo, si T =
0,1 s, el sistema no puede diferenciar entre eventos más cortos de 0,1 s. Otra consideración
importante es que la ejecución del programa que atiende la interrupción del RTC debe utilizar un
tiempo de procesamiento muy corto, para no limitar la capacidad del microcontrolador para ejecutar
otras tareas.
Para diseñar un RTC podemos utilizar la interrupción de uno de los temporizadores en el
microcontrolador. Por ejemplo, el Timer0 puede ser programado para generar una interrupción de
forma periódica (tic-tac del reloj) cada cierto número de milisegundos.
Esto se hace mediante el uso de una variable (una variable que cuenta los TICKS del reloj) que
aumenta o disminuye con cada interrupción. Otras variables se puede usar para contar los
segundos, minutos, horas, etc. El siguiente ejemplo ilustra cómo implementar un RTC en el
PIC16F873.
Ejemplo 7.4
Reloj de tiempo real basado en un PIC16F873 con un cristal de 4 MHz. En el ejemplo se muestra
cómo implementar un RTC utilizando una base de tiempo variable para contar con los ticks,
segundos, minutos y horas.
Si Timer0 es programado con un módulo de cuenta N = 256 y el prescaler con un factor de división
de 32, generará una interrupción cada 8.192 ms (122,07 Hz). Para llegar a 1 segundo, es
necesario contar con 122 interrupciones (ticks) para el contador. El registro SEC implementa el
contador de segundos, el registro de MIN implementa el contador de minutos, y el registro HOURS
implementa el contador de horas.

Figura 7.11 muestra el algoritmo para el RTC. Aunque pueda parecer que este algoritmo toma una
gran cantidad de tiempo de microcontrolador, la realidad es diferente porque en la mayoría de los
casos el algoritmo sigue a la decisión NO. De las 122 interrupciones que se producen cada
segundo, sólo una toma la ruta de SI (bloque de decisión TICKS = 0?) y así sucesivamente. Por lo
tanto, el algoritmo utiliza un tiempo de procesamiento muy corto. Esto es muy deseable en un RTC.
En el algoritmo mostrado en la figura 7.11, la variable TICKS disminuye, mientras que SEC, MIN, y
HORA aumentan. La razón de este enfoque diferente es maximizar la velocidad de ejecución para
tomar la menor cantidad posible de tiempo de microcontrolador. Incrementando la variable TICKS y
comparando su valor con 122 serian necesarias más instrucciones que decrementando y
preguntando si su valor es cero. Por lo tanto, esta es la opción más rápida.

El siguiente es el código que implementa el algoritmo mostrado en la Figura 7.11:


;
, Reloj en tiempo real
, Utilizando interrupción Timer0
;
lista p = 16F873
# Include <p16f873.inc>
;
; Las variables de la base de tiempo:
;
TICKS equ 0x20 ; contador de ticks.
SEC equ 0x21 ; contador de segundos.
MIN equ 0x22 ; contador de minutos.
HOUR equ 0x23 ; Cuenta horas.
;
; Otras variables:
;
TEMP_W equ 0x24
TEMP_ST equ 0x25
;
org 0
Ir a inicio
org 4
Ir a rtc
;
init:
clrf INTCON ; Deshabilitar todas las interrupciones.
bsf STATUS, RP0 ; Selecciona banco 1.
movlw 0xC4 ; preescalador con un factor de 32.
movwf OPTION_REG ; asignados a TIMER0.
Figura 7.11
Diagrama de bloques con el algoritmo para el reloj en tiempo real del ejemplo 7.4. La base de tiempo es
realizadas por la variable TICKS, SEC, MIN y HORA que cuentan los ticks, segundos minutos y horas del
reloj. El algoritmo es muy rápido porque la mayoría de las veces toma el camino "no" en la primera rama de
decisión. El algoritmo es totalmente ejecutado (en todos los caminos "sí") solo una vez al día (justo a la
medianoche!).

bcf STATUS, RP0 ; Selecciona banco 0.


movlw .0 ;módulo de cuenta = 256
movwf TMR0 ; en Timer0.
movlw .122 ; número de ticks por segundo.
movwf CLICK ;en el contador de ticks.
clrf SEC ; Contador de Segundos a 0.
clrf Min ; Acta contador a 0.
clrf HORA ; horas contador a 0.
bsf INTCON, T0IE ; TIMER0 Habilitar interrupción.
bsf INTCON, GIE ; habilitar las interrupciones globales.
;
prog: ; programa principal aquí.
nop
goto prog ; bucle infinito.
;
rtc:
movwf TEMP_W ; almacena W en TEMP_W.
swapf STATUS, W ; intercambio de nibbles STATUS,
bcf STATUS, RP0 ;selecciona banco 0
movwf TEMP_ST ;y almacena resultado en TEMP_ST.
;
bcf INTCON, T0IF ; Ajuste a la bandera de desbordamiento 0
; TIMER0.
decfsz TICKS, f ; alcanzado un segundo?
goto end_rtc ; No, dejar que la interrupción.
rtc_sec: ; Sí, llegó segundo.
movlw .122 ; TICKS Actualizar variable
movwf TICKS ; al valor inicial y
INCF SEC, f ; segundos de incremento.
movf SEC, W
xorlw 0,60 , SEC = 60?
btfsc STATUS, Z ;
goto end_rtc ; n, el retorno.
rtc_min: ; Sí, un minuto alcanzado.
clrf SEC ; poner los segundos a 0 y
INCF Min, f ; minutos incremento.
movf Min, W
xorlw . 60 , Min = 60?
btfsc STATUS, Z ;
goto end_rtc ; n, el retorno.
rtc_hour: ; Sí. Una hora llegó.
clrf Min ; Ajuste los minutos a 0 y
INCF HORA, f , las horas de incremento.
movf HORAS, W
xorlw 0,24 ; HORA = 24?
btfsc STATUS, Z ;
goto end_rtc ; n, el retorno.
rtc_day: ; Sí. Transcurrido 24 horas.
clrf HORA ; Establecer hora a 0.
end_rtc:
swapf TEMP_ST, W ; TEMP_ST Recuperar y aperitivos de intercambio
movwf STATUS ; almacenados en STATUS. El banco
; Seleccionados
; Ahora es el original en el
; TEMP_W es.
swapf TEMP_W, f ; TEMP_W recuperar y almacenar en
swapf TEMP_W, W , W sin alterar ESTADO.
retfie ; Volver al programa interrumpido.
;
end ; Fin del código fuente.
Reloj de Tiempo Real - Sincronización de eventos

Un RTC con una base de tiempo que cuenta fracciones de segundos, segundos, minutos,
y así sucesivamente nos permite sincronizar varios eventos con esta base de tiempos. Con esto,
cada evento ocurre periódicamente a iguales o diferentes intervalos de tiempo. Figura 7.12 ilustra,
mediante un caso concreto, la forma de proceder en general, para sincronizar eventos con una
base de tiempo basada en un RTC. En este caso, hay dos eventos llamados EVENT1 y EVENT2
que deben ser ejecutados periódicamente a cada 3 y 5 segundos. El procedimiento para lograrlo se
describe a continuación.
El programa RTC debe tener tantas variables como eventos necesarios para ser
sincronizados. Cada una de estas variables define el tiempo de repetición para el evento. En este
ejemplo, los eventos deben ser ejecutados cada 3 y 5 segundos.
Por lo tanto, el programa RTC debe tener dos variables que se incrementan cada segundo hasta
que alcanzan los 3 y 5 segundos, respectivamente. En la Figura 7.12, estos variables se
denominan SEC3 y SEC5. El programa RTC también debe tener una bandera para cada
evento que se va a sincronizar. Estos indicadores se establecen en 1 cuando el tiempo para
ejecutar el evento se ha alcanzado. Estos indicadores pueden ser bits en cualquiera de los
registros del microcontrolador. El ejemplo que se muestra en la Figura 7.12 utiliza los bits 0 y 1 de
un registro llamado FLAGS.
El programa principal comprueba periódicamente el estado de estos indicadores. Si encuentra
alguno de ellos a 1, significa que el evento debe ser ejecutado. Esto se hace llamando a la
subrutina que implementa la acción apropiada.
Después que el evento ha sido ejecutado, la bandera debe establecerse de nuevo a 0. Desde
un punto de vista de programación, estos indicadores son variables globales, porque deben tener
acceso tanto por el programa principal como por el programa de servicio de interrupción.

Ejemplo 7.5
Sincronizando dos eventos a una base de tiempos. Usando un PIC16F873 con un cristal de 4 MHz,
implementar un RTC, una base de tiempo, y ejecutar dos eventos asociados con la base de
tiempo:
1. El valor en el pin RB0 debe alternar entre 0 y 1 cada 3 s.
2. El valor en el pin RB1 debe alternar entre 0 y 1 cada 5 s.
La solución a este problema sigue el algoritmo se muestra en la figura 7.12. Usando el clock de 4
Mhz, programando el Timer0 con un módulo de conteo de N = 256 y utilizando un factor de división
de P = 32 para el prescaler, la interrupción de Timer0 ocurre cada 8.192 ms (122,07 Hz). Para
llegar a 1 s, es necesario contar con 122 interrupciones (ticks) en el contador. El programa utiliza
un registro (ticks) para contarlos. Registros SEC3 y SEC5 se utilizan para implementar contadores
0 a 3 segundos y de 0 a 5 segundos. Para indicar que 3 segundos o 5 segundos se han alcanzado,
el programa utiliza el bit 0 y el bit 1 del registro FLAGS (FLAGS<0>, FLAGS<1>). Estos bits son
seteados a 1cada 3 y 5 segundos. El programa principal comprueba su valor y los retorna a 0
cuando se produce el evento.
(a) (b)

Figura 7.12
Sincronización de eventos de RTC. EVENT1 y EVENT2 se ejecutan cada los 3 y 5 segundos.
(A) Diagrama de bloques para el RTC con los contadores SEC3 y SEC5 que se incrementan cada
un segundo hasta llegar a 3 y 5 segundos, respectivamente. Los bits 0 y 1 en el registro FLAGS
indican la ocurrencia de estos tiempos. (B) Diagrama de bloques para el programa principal que
continuamente comprueba el valor de los indicadores de tiempo para ejecutar los eventos
adecuados. Los bits de bandera se establece en 1 por el programa RTC y son puestos a cero por
el programa principal.

El código del programa se muestra a continuación:

;
, Reloj de tiempo real utilizando interrupción de Timer0.
; Esta base de tiempo sincroniza los eventos EVENT1 y EVENT2,
, Cada 3 y 5 segundos.
;
lista p = 16F873
# Include <p16f873.inc>
TICKS equ 0x20 ; contra garrapatas.
SEC3 equ 0x21 ; contador de segundos hasta 3.
SEC5 equ 0x22 ; contador de segundos hasta a 5.
FLAGS equ 0x23 ; banderas de eventos en los bits 0 y 1.
TEMP_W equ 0x24
TEMP_ST equ 0x25
org 0
goto inicio
org 4
goto rtc
inicio: ;programa principal
clrf PORTB
clrf INTCON ; deshabilita las interrupciones.
bsf STATUS, RP0 ; Selecciona banco 0.
movlw 0xC4 ; preescaler, con valor 32 asignado
movwf OPTION_REG ; a TIMER0.
clrf TRISB ; puerto B como salida.
bcf STATUS, RP0 ; Selecciona banco 0.
movlw 0,0 ; módulo de cuenta = 256
Movwf TMR0 ; en Timer0.
movlw .122 ; número de pasos por segundo.
movwf TICKS ;
clrf SEC3 ; SEC3 contador a 0.
clrf SEC5 ; SEC5 contador a 0.
clrf TICKS ; Bandera de eventos a 0.
bsf INTCON, T0IE ; Timer0 Habilita interrupción.
bsf INTCON, GIE ; habilitar la interrupción global del sistema.
prog:
btfsc FLAGS, 0 ; FLAGS<0> = 0?
call even1 ; No, llamar a event 1.
btfsc FLAGS, 1 ; FLAGS<1> = 0?
call even2 ; No, llamar a event 2.
goto prog
event1:
bcf FLAGS, 0 ; establecer FLAGS<0> a 0
btfsc PORTB, 0 ; PORTB<0> = 0?
goto event1_set0 , No. Esta a 1. Setearlo a 0.
event1_set1: ; Sí. Esta a 0. Setearlo a 1.
bsf PORTB, 0
return
event1_set0: ; establece en 0.
bcf PORTB, 0
return
event2:
bcf FLAGS, 1 ; establecer FLAGS<1> a 0.
btfsc PORTB, 1 ; PORTB<0> = 0?
goto event1_set0 , No. Esta en 1. Setearlo a 0.
event2_set1: ; Sí. Esta en 0. Setearlo a 1
bsf PORTB, 1
return
event2_set0: ; establece en 0.
bcf PORTB, 1
return
rtc: ;subrutina de servicio de interrupción
movwf TEMP_W ; almacena W en TEMP_W.
swapf STATUS, W ; intercambio de nibbles de STATUS,
bcf STATUS, RP0 ; selecciona banco 0
movwf TEMP_ST , y almacena el resultado en TEMP_ST.
bcf INTCON, T0IF ; borra el flag de Timer0?
decfsz TICKS, f ; llego a un segundo?
goto end_rtc ; No. Sale de interrupción.
;
rtc_sec:
movlw .122 ; Sí. Actualiza el valor del ticks.
movwf TICKS , con el número de ticks por
;segundos.
incf SEC3, f ; Incremento el contador de 3 segundos.
incf SEC5, f ; incremento el contador de 5 segundos.
;
movf SEC3, w
xorlw 0,3 ; SEC3 = 3?
btfsc STATUS, Z;
goto rtc_sec1 ; No. Continuar.
clrf SEC3 ; Sí. 3 segundos transcurridos. Setea SEC3 en 0,
bsf FLAGS, 0 ; establece en 1 la bandera FLAGS<0>
, Y continua.
rtc_sec1:
movf SEC5, w
xorlw 0,5 ; SEC5 = 5?
btfsc STATUS, Z ;
goto end_rtc ; No. Continuar.
clrf SEC5 ; Sí. 5 segundos transcurridos. Setea SEC5 a 0,
bsf FLAGS, 1 ; establece en 1 la bandera FLAGS<1>
, Y continua.
end_rtc:
swapf TEMP_ST, W ; Recupera TEMP_S y almacena en STATUS
movwf STATUS ; intercambiando nibbles. El banco seleccionado
; ahora es el original donde esta
;TEMP_W.
swapf TEMP_W, F ; recupera TEMP_W y lo almacena en
swapf TEMP_W, W , W sin alterar STATUS.
retfie ; Retorna al programa interrumpido.
end

S-ar putea să vă placă și