1. UNIDAD IV
TEMPORIZADOR TMR0 E INTERRUPCIONES
Objetivo general
Conocer los temporizadores y las interrupciones básicas presentes en el
microcontrolador PIC16F84.
Objetivos específicos
Estudiar los registros asociados al Timer 0.
Estudiar el funcionamiento del Timer 0.
Realizar cálculos para temporizaciones con el Timer 0.
Realizar programas para el uso del Timer 0.
Conocer el funcionamiento de las Interrupciones
Conocer las causas de una interrupción.
Realizar programas para el uso de las interrupciones.
Estudiar las estructuras de los programas con interrupciones.
Contenido
4.1. Conociendo los registros asociados al Timer 0 (TMR0).
4.2. Temporizador/Contador Timer 0 (TMR0).
4.2.1. ¿Qué es el prescaler?
4.3. Diagrama de bloque del Timer 0.
4.4. ¿Cómo cuenta el Timer 0?
4.5. Cálculos con el Timer 0.
4.5.1. ¿Otra forma de hacer los cálculos?
4.6. Uso de registro auxiliar.
4.7. De los cálculos a la programación.
4.8. Las Interrupciones.
4.9. Diagrama de flujo de una interrupción
4.10. Causas de interrupción en el PIC16F84
4.11. Registro INTCON.
4.12. Salvando y restaurando el entorno durante una interrupción.
4.13. Estructura de un programa con interrupción.
4.14. ¿Cuándo utilizar una interrupción?
4.15. Resumen de la Unidad IV.
4.16. Autoevaluación.
4.17. Ejercicios propuestos.
4.18. Lecturas complementarias recomendadas.
2. 4.1. Registros asociados al Temporizador/Contador Timer 0 (TMR0)
En la unidad III, realizamos rutinas de retardo sin el uso del Timer 0, al
hacer “perder” tiempo al microcontrolador ejecutando lazos de dos o más
registros que se decrementaban generando un retardo deseado, previamiente
calculado.
En esta unidad, estudiaremos un módulo temporizador/contador
dedicado a tal uso (El Timer 0), que nos permitirá generar retardos en base a
cálculos que serán explicados más adelante. Sin embargo, la ventaja principal
de los temporizadores, radica en que se pueden programar, en conjunto con
las interrupciones, para que efectúen procesos y/o tareas, cada cierto tiempo
de manera automática, mientras el microcontrolador se encuentra realizando
otras actividades. Por ejemplo, mientras monitoreamos el valor de un bit de
entrada, podemos programarlo para que cada 50 milisegundos (ms), el
microcontrolador entre en una subrutina a realizar otra actividad y regrese a
seguir monitoreando dicho pin de entrada.
Antes de empezar con la definición del temporizador/contador Timer 0,
veamos los registros asociados a su funcionamiento y operación en la siguiente
tabla:
De allí observamos los siguientes registros:
• TMR0: Registro de 8 bits de lectura/escritura
• OPTION_REG: Configura al TMR0 para que trabaje como temporizador
ó contador y asigna el valor al prescaler
• INTCON: Da información mediante el bit “TOIF” cuando el TMR0 se ha
desbordado.
• TRISA (PUERTO A): Permite el ingreso de pulsos cuando el TMR0 está
configurado como contador por RA4.
Analicemos el funcionamiento del registro OPTION_REG: este registro
es el equivalente a los TRIS de los puertos, nos permite configurarlo para que
el Timer 0 sepa cómo debe “comportarse” y/o funcionar.
Entre sus atributos, observamos que permite la selección del modo de
trabajo del Timer 0, elige el valor de la división de la frecuencia que ingresa al
microcontrolador, entre otras:
3. Registro OPTION_REG (Dirección 81H)
7 (L/E) 6 (L/E) 5 (L/E) 4 (L/E) 3 (L/E) 2 (L/E) 1 (L/E) 0 (L/E)
RBPU INTEDG TOCS TOSE PSA PS2 PS1 PS0
bit 7, RPBU : Resistencia Pull-up del Puerto B.
1: Desactivadas
0: Activadas
bit 6, INTEDG: Flanco activo para el control de interrupciones
1: Con flanco Ascendente
0: Con flanco Descendente
bit 5, TOCS: Fuente de Reloj para TMR0
1: Pulsos introducidos a través de RA4/T0CK1 (Contador)
0: Pulsos de reloj interno Fosc/4 (Temporizador)
bit 4, TOSE: Tipo de flanco en TOCK1
1: Incremento de TMR0 cada flanco descendente
0: Incremento de TMR0 cada flanco ascendente
bit 3, PSA: Bit de asignación del prescaler divisor de frecuencia
1: El divisor de frecuencia se asigna al WDT
0: El divisor de frecuencia se asigna al TMR0
bit 2-0, PS2:PSO: Rango con el que actúa el divisor de frecuencia.
Valor del los Bits Factor de división Factor de
del TMR0 división del WDT
000 1:2 1:1
001 1:4 1:2
010 1:8 1:4
011 1:16 1:8
100 1:32 1:16
101 1:64 1:32
110 1:128 1:64
111 1:256 1:128
Ejemplo de configuración del registro OPTION_REG.
1. Configure al PIC16F84 para que el temporizador TMR0, trabaje con los
pulsos provenientes de un reloj externo, y el mismo cambie en el flanco de
subida o ascendente del pulso externo:
Respuesta. En base al registro OPTION_REG, debemos cargar los
siguientes valores:
x x 1 0 0 x x x
Estos valores a cargar en el registro OPTION_REG cumplen con lo
solicitado en el enunciado del problema o diseño, sobre las “x”, puede
colocarse cualquier valor, ya que no se han realizado especificaciones sobre
4. estas, sin embargo, es importante saber o conocer cuál será el factor de
división de la señal que ingresará al Timer 0.
2. Configure al PIC16F84 para que el TMR0, trabaje con el reloj interno y la
frecuencia del mismo sea dividida por 32:
Respuesta. En base al registro OPTION_REG, debemos cargar los
siguientes valores:
x x 0 x 0 1 0 0
Estos valores a cargar en el registro OPTION_REG cumplen con lo solicitado
en el enunciado del problema o diseño, sobre las “x”, puede colocarse
cualquier valor, ya que no se han realizado especificaciones sobre estas.
3. Configure al PIC16F84 para que el TMR0, trabaje con el reloj interno y la
frecuencia del mismo sea dividida por 16. Active las resistencias “Pull-Up”
del puerto B y configure que el flanco de activación de interrupción del pin
INTEDG del RBO sea por bajada o descendente:
Respuesta. En base al registro OPTION_REG, debemos cargar los
siguientes valores:
1 0 0 0 0 0 1 1
Estos valores a cargar en el registro OPTION_REG cumplen con lo
solicitado en el enunciado del problema o diseño, Sobre las resistencias “Pull-
up” del puerto B, son resistencias que internamente se conectan a VDD cuando
el puerto B trabaja como entrada de datos y que nos permiten ahorrar el
conexionado de resistencias adicionales a nuestro circuito, y sobre el tipo de
flanco seleccionado de activación del pin INTEDG del RB0, se refiere a la
manera en cómo se detectará la interrupción en este pin por cambio del nivel
de voltaje presente en su entrada. Esta interrupción RB0/INT, se estudiará en
el tema de interrupciones.
¿Cómo cargo los valores seleccionados al registro OPTION_REG?
Respuesta: Como cualquier otro registro con los que hemos trabajado:
En el primer ejemplo:
movlw b’xx100xxx’ ;recordando que x puede ser 0 ó 1.
movwf OPTION_REG
En el segundo ejemplo:
movlw b’xx0x0100’ ;recordando que x puede ser 0 ó 1.
movwf OPTION_REG
En el tercer ejemplo:
movlw b’10000011’
movwf OPTION_REG
De esta manera, el registro OPTION_REG se ha configurado para que el
Timer 0 trabaje con el enunciado o diseño que estemos realizando. En otras
palabras el registro OPTION_REG es la mano derecha del Timer 0.
5. 4.2. Temporizador/Contador Timer 0 (TMR0).
Es el registro asociado al Timer0. Se encuentra en la posición 01H de la
memoria RAM. Es el corazón del módulo Timer0. Puede ser leído o escrito en
cualquier momento. El TMR0 se incrementará automáticamente por cada ciclo
de instrucción y contará desde 0 (00H) hasta 255 (FFH) (Contador de 8 bits).
Para que opere como temporizador, el bit TOCS (del registro
OPTION_REG) debe ser cero (0), el bit PSA= 0 y deben ser cargados los bits
PS2 a PS0, según sea el preescaler a utilizar para lograr nuestra
temporización.
Para que opere como contador, se usa una entrada de reloj externo en
el TMR0 y se deben de cumplir ciertos requisitos para que el reloj externo
pueda ser sincronizado con el reloj interno (TOSC). Además existe un retardo
en el incremento real del TMR0, después de la sincronización. El bit TOCS= 1.
Se debe seleccionar el tipo de flanco que producirá el incremento del TMR0
(TOSE = 1 ó 0).
4.2.1. ¿Qué es el prescaler o Predivisor?
El prescaler o predivisor, divide la frecuencia de reloj de entrada del
Timer0, entre valores predefinidos, como se ve en la tabla asociada al registro
OPTION_REG, 1:32, 1: 64, 1:256, etc., genera una nueva señal de menor
frecuencia a la salida, que será la señal de reloj de entrada al registro TMR0.
El prescaler o predivisor “Ralentiza” señales de entrada demasiado
rápidas para nuestros propósitos.
También existe un postescaler, asociado al perro guardián WDT (Watch
Dog Timer) del microcontrolador, pero en este caso recibe el nombre de
postcaler ya que se usa a la salida del WDT, no pudiendo estar asignado a la
vez al Timer0 o al WDT. El preescaler es transparente para el programador, no
se puede leer ni escribir sobre él, pero se puede seleccionar por software,
como ya se ha dicho, mediante el registro OPTION_REG
Nota: Para evitar un RESET no deseado del sistema, es necesario ejecutar
una secuencia de instrucciones específicas cuando se cambia la asignación del
prescaler del TMR0 al WDT. Esta secuencia debe ser seguida, aún cuando el
WDT esté inactivo.
4.3. Diagrama de bloque del Timer 0
En la siguiente figura, podemos observar el diagrama de bloque del
Timer 0. En esta se distingue si la señal que ingresa al TMR0 proviene de una
fuente externa o interna (TOCS), si la señal es predividida (PS2:PS0) y si ha
sido asignada al Perro Guardián (WDT) o al TMR0, y mediante el bit TOIF
indica si el timer 0 se ha desbordado (al pasar de FFH a 00H).
6. 4.4. ¿Cómo cuenta el TMR0?
El TMR0 cuenta exclusivamente de forma ascendente, nunca lo hace de
manera descendente, y siempre se incrementa por cada ciclo de instrucción, no
se detiene.
00H
FFH
Y reinicia su
cuenta
00H
Si el TMR0 se carga con un valor, éste comenzará a contar desde el
valor cargado hasta que se desborda (cuando pasa a 00H)
(28-N10)
00H
FFH
Valor cargado
en el TMR0
00H
4.5. Cálculos con el TMR0.
Los cálculos con el TMR0 se realizan sobre tres sencillas fórmulas. A lo
largo de sus estudios usted ha aplicado fórmulas de mayor dificultad y
complejidad que las mostradas a continuación, por lo que no debe encontrar
obstáculos en la realización de estos cálculos.
Cuando se carga en el registro TMR0 un valor XXH, éste contará:
(FFH – XXH) impulsos y el tiempo que tarda en hacerlo viene dado por la
expresión:
7. Temporización= 4 * TOSC * Valor Real TMR0 * Rango del divisor de
Frecuencia. (1)
8
Valor Real TMR0 = (2 – N10) = (256 – N10) (2)
N10= Valor a cargar en el TMR0. (3)
Ejemplo 1: Sea un valor a cargar en el TMR0 de 100, un prescaler
seleccionado de 1:32 y un oscilador XT. Determine el tiempo en que
tardará el TMR0 en desbordarse.
Solución: Sea XT = Frecuencia = 4 MHz, T = 0.25 μs.
Temporización= 4*0.25 μs* (256 – 100) * 32 = 4.992 ms.
Ejemplo 2: Se desea saber: ¿Qué valor debemos cargar en el TMR0, si
deseamos obtener una temporización de 10,24 ms, utilizando un
preescaler de 128 y un cristal XT?
Solución: Despejando de la ecuación (1):
Temporizac ión 10 , 24 ms
(256 N 10 ) 80
4 TOSC Rgodivisor 4 0 . 25 s 128
(256 – N10) = 80, despejando N10 = (256 – 80) = 176, el valor que debemos
cargar en el TMR0 es 176, para que éste cuente desde 176 hasta 256.
Ejemplo 3: Elegir el valor del TMR0, para generar un retraso de 1.5 ms
utilizando un oscilador de 10 MHz.
Solución: Sea Fosc= 10 MHz, T = 100 ns
Temporización 1.5ms
(256 – N10 )
4 TOSC Rgodivisor 4 100ns RgoDivisor
N10 = 256 - (3750/RgoDivisor)
Démosle valores al Rango del divisor, hasta obtener un valor que se acerque lo
más posible al retardo propuesto:
Si Prescaler= 256, Valor a cargar en el TMR0= 241 (redondeado)
Si Prescaler= 128, Valor a cargar en el TMR0= 227 (redondeado)
Si Prescaler= 64, Valor a cargar en el TMR0= 197 (redondeado)
Si Prescaler= 32, Valor a cargar en el TMR0= 139 (redondeado)
Etc…
A manera de práctica, realice usted, el cálculo de la Temporización, para
cada uno de los valores que se consiguieron en los cálculos anteriores. Escoja
uno y justifique. Particularmente parece que el que tiene el rango de divisor de
64, es el mejor.
Nota: En este ejercicio resuelto, usted puede darse cuenta de que no hay un
solo resultado para los ejercicios, pero lo que si debe cumplirse es que sea
cualquiera que sean los valores que se tomen para los cálculos, estos deben
de estar cercanos a la respuesta que se espera del temporizador que esté
diseñando.
8. Ejemplo 4. Diga ¿cuánto es la máxima temporización que se puede hallar con
el TMR0? Asuma que se está trabajando con un XT.
Solución: Tomamos el máximo factor de escala de división todos los estados
que puede contar el TMR0:
Temporización= 4*0.25 μs*(256 )*256 = 65.536 ms.
Este es el máximo valor que podemos conseguir del TMR0.
4.5.1. ¿Otra forma de hacer los cálculos?
Si aún le enredan las fórmulas mostradas para calcular temporizaciones,
probemos con estas tres:
Pruebe ahora realizar los mismos cálculos siguiendo el 1, 2, 3…
4.6. Uso de registro auxiliar.
En el ejemplo 4, observamos que la máxima temporización que
podemos hallar con el TMR0 es 65.536 ms.
¿Cómo hacemos entonces para conseguir valores superiores a
éste, tales como 0,5 s; 1 s; 2 s; entre otros?
Esto se puede arreglar si tenemos un contador de mayor número de bits.
La solución está en extender el Timer0 con un registro (auxiliar) controlado por
software.
Dicho registro (auxiliar) contará el número de interrupciones por
desbordamiento que genera el Timer0, de forma de que éste pase por cero,
cuando haya pasado el tiempo que estamos calculando. Veamos el siguiente
diagrama de bloque:
TMR0= XX (ms) Registro Auxiliar= Valor Deseado=
YY (XX) ms * (YY)= (ZZ) ms
Pasos para seleccionar el Registro Auxiliar:
1. Escoger un valor para el prescaler.
Un posible criterio es calcular todas las frecuencias de prescaler que
podemos obtener con cada divisor posible. Las frecuencias sin decimales son
interesantes al poder encontrar múltiplos de ellas a la salida del TMR0 con
mayor facilidad. En general, la elección del valor del prescaler es empírica:
depende del problema, la experiencia y sobre todo de la práctica.
9. 2. Determinar el valor del Registro Auxiliar, a partir del valor dado por el
TMR0.
Normalmente viene dado por un múltiplo de la frecuencia, asociada al
tiempo calculado. Con un ejemplo entenderemos mejor lo que se desea
plantear:
Ejemplo: Determine los valores del TMR0 y del Registro Auxiliar para
conseguir una temporización de 1 segundo. Utilice un oscilador XT.
Solución: XT= Frecuencia = 4 MHz ; Tosc= 250 ns
• Paso 1. Como no se nos ha impuesto que prescaler utilizar ni que
temporización, podemos aleatoria mente escogerlas, como en el ejemplo 6.
Evaluando cualquiera, cuya temporización del TMR0 se basó en 5 ms,
escojamos el prescaler 128 y sustituyamos los valores en la ecuación
principal:
Temporización= 4*250 ns*(256 - 217)*128 = 4.992 ms
• Paso 2. ¿Qué valor debe de tener el registro auxiliar?
a) Al tiempo de 4.992 ms, se asocia una frecuencia del TMR0 de =
1
200.3 Hz
4.992ms
Redondeando, tomamos este múltiplo: 200, Así, tendremos entonces
que si multiplicamos 200*4.992 ms = 0.998 s, que es un valor bastante cercano
a 1 segundo.
b) La misma operación pero interpretada de una forma más sencilla es
determinar cuántas veces necesitamos al tiempo calculado para lograr un
segundo:
1segundo
200.32
4.992ms
La que usted entienda mejor es válida. Nuestro registro auxiliar debe ser
de 200.
Nota: Recuerde de que este registro auxiliar no debe superar 255.
Si supera este valor, se debe adicionar un nuevo registro auxiliar
4.7. De los cálculos a la programación
Realicemos un ejercicio completo:
1. Realice un programa que permita encender y apagar un led cada 15 ms,
mediante el timer0. Utilice un oscilador XT.
Solución: Cómo se ha sugerido desde la unidad II, para resolver un problema,
debemos dividirlo en tres partes básicas: El enunciado y la asignación de los
pines de entrada y de salida. El diagrama de flujo y el lenguaje ensamblador.
Sin embargo este problema consta de una parte adicional que incluye los
cálculos y que será la segunda en el orden antes mencionado.
Paso 1. Luego de leer el enunciado, podemos elegir cualquier pin por donde
generaremos nuestra señal cuadrada de 30 ms de período, o 15 ms el tiempo
en alto (TON) y 15 ms el tiempo en bajo (TOFF). Elijamos RA0.
10. Paso 2. Realicemos los cálculos necesarios, podemos asumir un prescaler o
predivisor cualquiera. En este ejemplo asumiremos 128, perfectamente
podemos asumir cualquier otro:
Temporización= 4 * TOSC * Valor Real TMR0 * Rango del divisor de
Frecuencia.
despejando:
Temporización 15ms
(256 – N10 ) 117.18
4 TOSC Rgodivisor 4 0.25s 128
Redondeando tomamos 117.
Despejando, del valor real a cargar en el TMR0= (256-117)= 139. Nota:
debemos cargar en el TMR0= 139 para que cuente 117 estados, hasta que se
desborde.
Verificando los cálculos:
Temporización= 4*250 ns*(256-139)*128= 14.98 ms.
Paso 3. Elaboremos el diagrama de flujo. Debemos de estructurar el programa
para que vigile e informe cuando el TMR0 se ha desbordado, y el bit que nos
da esta información es el TOIF, del Registro INTCON. Adicional a esto
debemos configurar el registro OPTION para que este trabaje con el prescaler
que hemos seleccionado para nuestros cálculos, así como de asignarlo al
TMR0. Así como la rutinaria configuración de los puertos.
INICIO
Configurar: Puerto A,
OPTION_REG, INTCON
1
Cargar TMR0 con
valor calculado
Cargar TMR0 con
valor calculado Led= on
NO ¿TOIF=1? NO
¿TOIF=1?
SI SI
TOIF=0 TOIF=0
Led= off
1
Paso 4. Elaboremos el Programa en lenguaje ensamblador. Una vez obtenido
el diagrama de flujo, realizar el programa se hace más sencillo al contar con
una guía de funcionamiento:
11. list P=16F84A
include P16F84A.INC
org 00H
goto INICIO
INICIO bsf STATUS,5
clrf TRISA
movlw B’11010110’
movwf OPTION_REG
bcf STATUS,5
clrf INTCON
LEDON bsf PORTA,0
call RETARDO
LEDOFF bcf PORTA,0
call RETARDO
goto LEDON
;*********************************
;***RUTINA DE RETARDO***
;*********************************
RETARDO movlw D’139’
movwf TMR0
ESPERA btfss INTCON,TOIF
goto ESPERA
bcf INTCON,TOIF
return
end
Ejercicio propuesto. Realice un programa que permita encender y apagar un
led cada un segundo. Mediante Timer0 y con un oscilador XT.
12. 4.8. Las interrupciones
“Las interrupciones son desviaciones del flujo de control del programa
originadas asíncronamente, por diversos sucesos que no se hallan bajo la
supervisión de las instrucciones. Dichos sucesos pueden ser externos al
sistema, como la generación de un flanco o nivel activo en una patilla del
microcontrolador, o bien, internos, como el desbordamiento de un contador. Su
comportamiento es similar al de la instrucción “call” de llamado a subrutina. Se
detiene la ejecución del programa en curso, se salva la dirección actual del
contador de programa (PC) en la pila (STACK) y se carga el PC con una
dirección, que en el caso de una interrupción es una dirección reservada de la
memoria de código, llamada vector de interrupción”. Parejo. Microcontroladores
PIC. Pág. 117. 2da Edición.
• En el PIC 16F84, este vector de interrupción está ubicado en la posición
04H, en donde comenzará la rutina de servicio de la interrupción.
Ejemplo:
org 00H ; Vector de origen del programa
goto INICIO ; salto a la rutina de programa principal
org 04H ; Vector de interrupción
goto INTERR ; salto a la rutina de interrupción.
13. La idea de colocar una instrucción de salto incondicional, es la de
trasladar el flujo del programa a la zona de memoria de código que contiene a
la rutina de interrupción.
4.9. Diagrama de flujo durante una interrupción
El comportamiento del microcontrolador durante una interrupción es
similar al mostrado durante la llamada a una subrutina, con la diferencia de que
el llamado no se hace mediante la instrucción “call”, si no con previa
configuración de las interrupciones disponibles para cada modelo de
microcontrolador.
Una vez que se han configurado las interrupciones con los permisos y/o
habilitaciones correspondientes, el microcontrolador podrá seguir ejecutando el
programa principal y cuando ocurra un evento dentro de las interrupciones
disponibles y habilitadas previamente, el microcontrolador dejará de hacer la
tarea actual y entrará en la subrutina de servicio de interrupción (RSI) y sólo
saldrá de esta cuando ejecute la instrucción retfie.
4.9.1. Diagrama de flujo durante una interrupción
INICIO PROX
PCL
21H instrucción A instrucción 1
22H instrucción B instrucción 2
23H instrucción C instrucción 3
24H instrucción D retfie
25H instrucción E
Nota: una Rutina de Servicio de
Interrupción puede ser igual de
instrucción F
26H extensa o más, que el mismo
programa principal.
end
14. RSI
PC pasa a
PILA
PC=04H
Rutina de Interrupción
Se almacenan
registros a modificar
Se determina causa de
interrupción y se ejecuta
Se salvan registros
guardados
Se borran los
señalizadores
Retorno (retfie) Se extrae
de la pila el PC. GIE= 1
4.10. Causas de interrupción en el PIC16F84
1. Activación (Cambio de nivel lógico) del pin RB0/INT
2. Desborde del TMR0 (al pasar de FFH a 00H)
3. Cambio de estado de una de los 4 pines de más peso (RB7:RB4)
del puerto B (Ver Nota (1) en tema 4.13. Ejemplo 2)
4. Finalización de la escritura en la EEPROM de datos
4.11. Registro INTCON
Este registro se encarga de habilitar o permitir las interrupciones
disponibles en el PIC16F84, se encuentra ubicado en la posición 0BH del
banco 0 de los registros de funciones especiales (SFR). A continuación se
describirán cada uno de sus bits:
GIE EEIE TOIE INTE RBIE TOIF INTF RBIF
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
(L/E) (L/E) (L/E) (L/E) (L/E) (L/E) (L/E) (L/E)
15. Registro INTCON
GIE: (Global Interrupt Enable), Permiso Global de Interrupciones
1: Habilita todas las interrupciones, cuyos bits de permiso individuales
también las permitan
0: Deshabilita todas las interrupciones
EEIE: (EEPROM Interrupt Enable), Permiso de Interrupción por fin de
escritura en la EEPROM
1: Habilita la interrupción cuando termina la escritura de la EEPROM de
datos
0: Deshabilita esta interrupción
TOIE: (TMR0 Overflow Interrupt Enable), Permiso de interrupción por
desborde del TMR0
1: Habilita una interrupción por desborde del TMR0
0: Deshabilita esta interrupción
INTE: (Interrupt Enable RB0/INT), Permiso de interrupción por
activación del pin RB0/INT
1: Habilita la interrupción al activarse RB0/INT
0: Deshabilita esta interrupción
RBIE: (RB Port Change Interrupt Enable), Permiso de interrupción por
cambio de estado en RB7:RB4
1: Habilita esta interrupción
0: Deshabilita esta interrupción
TOIF: (TMR0 Overflow Interrupt Flag), Señalizador de desborde del
TMR0
1: Ha ocurrido un desborde del TMR0
0: No se ha desbordado el TMR0
INTF: (RB0/INT Interrupt Flag), Señalizador de activación del pin
RB0/INT
1: Se ha activado RB0/INT
0: No se ha activado RB0/INT
RBIF: (RB Port Change Interrupt Flag), Señalizador de cambio de
estado en RB7:RB4
1: Pasa a 1 cuando cambia el estado de alguna de estas 4 líneas
0: No ha cambiado el estado de RB7: RB4
4.12. Salvando el entorno
Salvar el entorno, se refiere a mantener el valor exacto que tienen los
registros de trabajo STATUS y W, y cualquier otro de importancia, que no vaya
a ser modificado dentro de la subrutina de servicio de interrupción.
Para salvar el entorno cuando ocurre una interrupción se recomienda
seguir los siguientes pasos:
1. Salvar a w y a STATUS.
2. Almacenar a w en un registro general llamado W_TEMP
3. Almacenar a STATUS en un registro general llamado STATUS_TEMP
4. Se ejecuta la rutina de interrupción (queda expresada para efectos del
ejemplo siguiente)
16. 5. Restauramos a STATUS
6. Restauramos a w
NOTA: Los registros generales W_TEMP, STATUS_TEMP, deben ser
declarados al inicio del programa, para no generar errores.
; **** Rutina para salvar el entorno ****
PUSH movwf W_TEMP ; Copiamos w a este registro temporal
swapf STATUS,0 ; Intercambiamos STATUS y lo
; guardamos en w
movwf STATUS_TEMP ; Salvamos STATUS en
; STATUS_TEMP
RUT_INT ;
; Aquí estará la rutina de servicio de interrupción
;
POP swapf STATUS_TEMP,0 ; Intercambiamos nibbles en el
; registro STATUS_TEMP
movf STATUS ; Movemos w al registro STATUS,
; retornando el valor original
swapf W_TEMP,1 ; Intercambiamos nibbles y lo
; mantenemos en este registro
swapf W_TEMP,0 ; Intercambiamos nibbles y lo
; trasladamos a w retornando el valor
; original que tenía antes de
; entrar a la rutina de interrupción
4.13. Estructura de un programa con interrupción.
En el tema 4.9.1 observamos el diagrama de flujo durante una
interrupción, se puede apreciar que existen dos diagramas de flujos, uno para
el programa principal y otro para la subrutina de servicio de interrupción (RSI),
con un similar comportamiento al descrito sobre las subrutinas de usuario
estudiadas en la unidad III.
Cuando trabajamos con el lenguaje ensamblador, se debe insertar el
vector de interrupción (org 04H), para que el programa tenga la dirección a
dónde dirigirse a ejecutar la RSI, tal como se hace de forma similar con la
instrucción call k, de las subrutinas de usuario.
Generalmente la RSI se declara al inicio del programa, antes del
programa principal, sin embargo algunos autores la colocan al final del mismo.
Es importante resaltar que así como la subrutina de usuario está enmarcada
entre la etiqueta (k) y una instrucción return o retlw k, la RSI estará enmarcada
entre la dirección del vector de interrupción y la instrucción retfie.
Veamos el siguiente ejemplo para entender mejor la estructura:
17. Ejemplo 1.
Opción A. Antes del programa principal:
list P=16F84A
include P16F84A.inc
org 00H ; Vector de inicio
goto INICIO
org 04H ; Vector de interrupción
goto RSI ; La RSI puede ir inmediatamente
RSI bcf INTCON,7 ; Deshabilitamos las interrupciones
btfss INTCON,2 ; La causa fue por desborde del TMRO
goto SALIRINT ; Si es no, salimos de la RSI
movlw 0FFH ; Si es la causa, ejecutamos la rutina de
; ejemplo.
xorwf PORTB ; Generamos una señal cuadrada
SALIRINT bcf INTCON,2 ; Borramos el señalizador TOIF
bsf INTCON,7 ; Habilitamos las interrupciones
retfie ; Salimos de la RSI.
INICIO bsf STATUS,5 ; Banco 1
clrf TRISB ; Puerto B como salida
movlw b’10000111’ ; TMR0, Temporizador, 1:256
movwf OPTION_REG
bcf STATUS,5 ; Banco 0
movlw B’10100000’
movwf INTCON ; Se activa el GIE y el TOIE
clrf PORTB ; Inicializamos PORTB=0
SINFIN clrwdt
goto SINFIN ; Bucle sin fin, para este ejemplo.
end ; Fin del programa
Opción B. Luego del programa principal:
list P=16F84A
include P16F84A.inc
org 00H ; Vector de inicio
goto INICIO
org 04H ; Vector de interrupción
goto RSI ; La RSI puede ir inmediatamente
INICIO bsf STATUS,5 ; Banco 1
clrf TRISB ; Puerto B como salida
movlw b’10000111’ ; TMR0, Temporizador, 1:256
movwf OPTION_REG
bcf STATUS,5 ; Banco 0
movlw B’10100000’
18. movwf INTCON ; Se activa el GIE y el TOIE
clrf PORTB ; Inicializamos PORTB=0
SINFIN clrwdt
goto SINFIN ; Bucle sin fin, para este ejemplo.
RSI bcf INTCON,7 ; Deshabilitamos las interrupciones
btfss INTCON,2 ; La causa fue por desborde del TMRO
goto SALIRINT ; Si es no, salimos de la RSI
movlw 0FFH ; Si es la causa, ejecutamos la rutina de
; ejemplo.
xorwf PORTB ; Generamos una señal cuadrada
SALIRINT bcf INTCON,2 ; Borramos el señalizador TOIF
bsf INTCON,7 ; Habilitamos las interrupciones
retfie ; Salimos de la RSI.
end ; Fin del Programa.
Ejemplo 2. Realicemos un programa completo que contenga varias
interrupciones. Si la causa ha sido la activación del pin RB0, se debe mostrar
un dos en binario en el puerto A, si ha sido un cambio de nivel en RB4:RB7, se
debe mostrar el uno en binario en el puerto A y si se ha desbordado el TMR0,
se debe mostrar el cuatro en binario en el puerto A.
Paso 1. Dibujar el diagrama de flujo:
19. Paso 2. Lenguaje ensamblador
LIST P=16F84A
INCLUDE P16F84A.INC
W_TEMP equ 20H ; Se declaran los registros generales para
ESTADO_TEMP equ 21H ; salvar los registros STATUS y W
org 00H
goto INICIO
org 04H ; Se coloca el vector interrupción para que se
goto RUTINTERR ; Ejecute la rutina de interrupción
RUTINTERR
movwf W_TEMP ; Se inicia a la rutina de servicio de
; interrupción
swapf W_TEMP,1
movf STATUS,0
movwf ESTADO_TEMP
btfsc INTCON,0 ; Se empieza exploración de causa de
; interrupción
goto INTERRB47 ; Si RBIF=1, se va a ejecutar
btfsc INTCON,1
goto INTERRB0 ; Si INTF=1, se va a ejecutar
btfsc INTCON,2
goto INTERRTMR ; Si TOIF=1, se va a ejecutar
goto SALIRINT ; Si no es ninguna, se sale de la
; interrupción
SALIRINT bsf INTCON,7 ; Se habilita GIE, para permitir de
; nuevo otra Interrupción
movf ESTADO_TEMP,0 ; y se restaura el entorno
movwf STATUS
swapf W_TEMP,0
retfie ; El uso de return o retlw k, puede producir
; errores en la ejecución del programa
;*** Subrutina de tratamiento de cambio de RB4:RB7 ***
INTERRB47 bcf INTCON,0
movlw 01H
movwf PORTA
movf PORTB,0 ; Ver NOTA (1)
bcf INTCON,0 ; Se borra por software el señalizador
; de esta Interrupción
goto SALIRINT
;*** Subrutina de tratamiento de activación de INT/RB0 ***
INTERRB0
movlw 02H
movwf PORTA
bcf INTCON,1 ; Se borra por software el señalizador
goto SALIRINT
20. ;*** Subrutina de tratamiento del desborde del TMR0 ***
INTERRTMR
movlw 04H
movwf PORTA
movlw d'200' ; Se carga el valor calculado para el
; TMR0 para asegurarnos
movwf TMR0 ; que al regresar tenga este valor
bcf INTCON,2 ; Se borra el señalizador
goto SALIRINT
;*************PROGRAMA PRINCIPAL****************
INICIO bsf STATUS,5
clrf TRISA ; PORTA como entrada
movlw 0FFH
movwf TRISB ; PORTB como entrada
movlw b'01000000'
movwf OPTION_REG
; Diga: ¿Cómo se configuró OPTION?
bcf STATUS,5
movlw b'10111000' ; Se habilita GIE y las interrupciones
movwf INTCON ; Individuales
DORMIR nop
movlw d'240'
movwf TMR0 ; Diga: ¿Qué valor de temporización
; tendrá el TMR0?
SINFIN CLRWDT
goto SINFIN ; Se coloca al microcontrolador en
; bucle o lazo sin fin
end
; Nota (1): En este tipo de interrupción, internamente el procesador lee el nibble
; alto del puerto B y hace una copia, la interrupción se genera cuando la lectura
; del nibble alto del puerto B es diferente de la copia.
; Dentro de la ejecución de esta rutina de interrupción es importante que se lea
; el puerto B, para actualizar la copia, y el procedimiento adecuado es el
; mostrado anteriormente.
4.14. ¿Cuándo utilizar una interrupción?
Una interrupción es muy importante cuando deseamos realizar una tarea
que no dependa de una exploración constante del programa sobre la misma.
Esto le agrega al microcontrolador independencia para realizar procesos
paralelos, es decir, mientras se ejecuta un programa determinado, de forma
alterna se puede estar a la espera de que ocurran algunas de las
interrupciones mencionadas sin necesidad de monitorearlas por sondeo o
exploración. Apenas ocurran, la RSI se ejecutará y se realizará el tratamiento
previamente diseñado.
21. También cuando deseamos que nuestro programa responda de forma
inmediata y automática a determinados eventos.
Ejemplo del uso de Interrupción:
• En los sistemas de control, cuando se necesita un pulsador de parada de
emergencia (PARE).
• En un diseño, cuando se requiere que nuestro circuito cumpla con
determinadas tareas, al pulsarse una tecla (LAMP TEST en los displays).
• En el manejo de teclados, se recomienda su uso, ya que se puede meter al
microcontrolador en un estado de reposo, ahorrando energía y esperando a
que se pulse una tecla para iniciar una rutina de servicio (CLAVE).
• Cuando deseamos que nuestro programa entre a monitorear una función o
subrutina cada cierto tiempo, mediante el desborde del TMR0.
• Cuando almacenamos información en la EEPROM y deseamos ser
advertidos de que ésta se ha terminado (ALMACENAMIENTO).
4.15. Resumen de la Unidad IV.
Al finalizar la unidad IV, se han dado a conocer dos importantes recursos
de los microcontroladores, a saber, el temporizador TMR0 y las interrupciones.
Estos recursos nos permiten dar libertad de acción a los microcontroladores, al
permitir ejecutar tareas cada cierto tiempo, de manera alterna o paralela al
programa principal mediante la combinación de la temporización y las
interrupciones, sin tener que estar monitoreando estas tareas adicionales.
Algunas interrupciones sirven para monitorear de manera automática un
teclado, mientras se puede controlar un proceso, así como detectar un pulsador
o un cambio de nivel en el pin RB0.
Las interrupciones, previa configuración, responden de manera
inmediata y automática al evento seleccionado entrando en una subrutina de
servicio de interrupción sin necesidad de ser llamada como las subrutinas de
usuario.
El uso del temporizador TMR0 permite generar señales cuadradas con
un amplio rango de frecuencias, similar a como lo hace el 555, sólo que nos
ahorramos hardware adicional, al realizarlo totalmente por software,
convirtiendo al microcontrolador en una herramienta más completa.
En circuitos Digitales, para diseñar un reloj digital con horas, minutos y
segundos, se necesitan al menos 14 circuitos integrados, con las herramientas
vistas en la unidad III y en la unidad IV, el hardware necesario para esta tarea
se reduce notablemente a 2 circuitos integrados, reduciendo los costos de
construcción y de espacio.
22. Aplicaciones como un frecuencímetro pueden ahora lograrse mediante el
programa adecuado, y todo en un solo circuito integrado de un
microcontrolador.
Las potencialidades y aplicaciones se abren limitándose en un inicio a
las ideas de los usuarios.
4.16. Autoevaluación.
¿Qué usos se les puede dar al temporizador TMR0?
¿Qué registros son necesarios para trabajar con el TMR0?
¿Cuál es la función del registro OPTION_REG?
¿Cuál es la función del predivisor?
¿Cómo se logra una temporización superior a 65,35 ms con el TMR0?
¿Qué es una interrupción?
¿Cómo se comporta una interrupción en un programa?
¿Cuál es la función del registro INTCON?
¿Cuáles son las causas de interrupción en un PIC16F84?
4.17. Ejercicios propuestos.
1. Genere una señal cuadrada del 50 % del Ciclo útil con una frecuencia de 1
KHz.
2. Diseñe un contador de vehículos con el TMR0, cuyo resultado se muestre
por el puerto B.
3. Realice un temporizador programable de tres cifras (999 a 000). El circuito
asociado al programa posee un pulsador de ajuste, que permite variar y/o
fijar la cifra al valor que se desea temporizar. Debe realizar un conteo
descendente a razón de 1 segundo. Debe contar con un pulsador que
permita verificar que todos los segmentos están en buen estado (Función
“Lamp Test”) en cualquier momento. Debe encender un led, cada vez que
llegue a 000 y se detiene el conteo. Debe de tener un pulsador de inicio,
para que empiece la cuenta regresiva, una vez pulsado, no influye sobre la
temporización. Debe tener un pulsador que permita reestablecer el sistema
(poner a 999). Introduzca eliminarebotes (5 ms), para los pulsadores de
ajuste e inicio. Nota: Diseño libre.
4. Se desea realizar un programa que permita la ejecución de los siguientes
estados, bajo un mismo display:
23. Y luego del séptimo estado, empieza de nuevo en el estado 0.
El circuito asociado al programa debe tener dos interruptores de ajuste
de tiempo, el cual incrementará el tiempo entre 0,25 segundos, 0,5 segundos, 1
segundo y 2 segundos. Debe contar con un pulsador que permita verificar que
todos los segmentos están en buen estado (Función “Lamp Test”) en cualquier
momento. Debe tener un pulsador de inicio, según sea el modo seleccionado.
Introduzca eliminarebotes (5 ms), para el pulsador de inicio. Nota: Diseño libre.
5. Realice un frecuencímetro, cuyas frecuencias están definidas en la
siguiente tabla:
Frecuencia Modo Entrada
(A2A1A0)
1 KHz 0 000
500 Hz 1 001
250 Hz 2 010
100 Hz 3 011
50 Hz 4 100
10 Hz 5 101
1 Hz 6 110
0,5 Hz 7 111
El circuito asociado al programa debe tener: Tres interruptores que
seleccionan el modo de operación, cuyo número equivalente en decimal, debe
ser visualizado en un display. Debe tener un pulsador de inicio y un pulsador de
reestablecimiento. Introduzca eliminarebotes (5 ms) para los interruptores.
Luego de haberse pulsado “Inicio”, si cambia la selección, cambia la frecuencia
según sea el modo. Nota: Diseño libre.
6. Se desea automatizar una lavadora “CHACACHACA” bajo dos modos de
lavado (uno de Lavado Rápido de 30 minutos de duración y otro de Lavado
Lento de 50 minutos de duración), el sistema constará de un pulsador de
INICIO y un interruptor selector de modo de lavado. Automatice bajo las
siguientes condiciones:
Se elige entre lavado rápido ó lento
Se presiona INICIO y realiza lo siguiente:
Se llena la CHACACHACA hasta el nivel de agua máximo; lava ó “bate”
por la mitad del tiempo; se detiene; se vacía; se llena otra vez de agua;
lava ó “bate” hasta que falten tres minutos; se detiene; se vacía; se llena
otra vez de agua; lava ó “bate” por el resto del tiempo; se vacía
nuevamente y emite una alarma sonora por espacio de 10 segundos; y
se detiene a la espera de un nuevo proceso de lavado.
Si no hay agua en el depósito de agua, se detiene el lavado, se cierra la
válvula de llenado y se emite una alarma sonora hasta que se solucione
24. el problema agregando agua al depósito hasta el nivel mínimo de
lavado.
ML: Motor de Lavadora. VD: Válvula de Desagüe. VLL: Válvula de
Llenado.
Nmínimo, Nmáximo, Nmínimo de lavado, Nivel de alarma: Sensores
de nivel.
7. Realice un temporizador programable para el motor de una correa
transportadora, que permite encenderle y apagarle, según sea el tiempo
seleccionado definido en la siguiente tabla:
Tiempo Modo Entrada (A2A1A0)
2,5 minutos 0 000
2 minutos 1 001
1,5 minutos 2 100
1 minuto 3 101
30 segundos 4 111
El circuito asociado al programa debe tener: Tres interruptores que
seleccionan el modo de operación, cuyo número equivalente en decimal, debe
ser visualizado en un display. Debe tener un pulsador de “INICIO”. Introduzca
elimina rebotes (10 ms) para los interruptores. Luego de haberse pulsado
“INICIO”, si cambia la selección, cambia el tiempo según sea el modo. Si el
estado de los pulsadores no aparece en la tabla, debe mostrase la letra “E” de
“Error” en el display y debe mantenerse el motor apagado. El sistema cuenta
con un pulsador que indique en cualquier momento, si todos los segmentos del
display se encuentran en buen estado. El sistema cuenta con un sensor de
temperatura que se activa cuando el motor se recalienta, en cuyo caso se
activa un led rojo y se apaga el motor, a la espera de que se pulse “INICIO”
para poder empezar el proceso nuevamente.
Nota: Diseño casi libre. (NO cuenta con decodificador para manejar el display)
25. 8. Realice la automatización de la mezcladora de pinturas, mostrada en la
figura, bajo la siguiente secuencia de funcionamiento:
El sistema de mezclado se inicia al pulsarse “MARCHA”, mediante el cual,
se activa B1, por espacio de por espacio de 13 segundos. B2, MM, VD, MA
deben estar apagados. Se enciende un led verde que indica que el sistema
esta en marcha.
Transcurrido este tiempo, se enciende B2. B1, MM, VD, MA, deben estar
apagados.
B2 se mantiene encendido hasta que el sensor “Nivel alto” se activa,
mediante el cual se detiene B2, se activa MM. B1, VD, MA, se mantienen
apagados.
MM se mantiene encendido por espacio de 1 minuto. B1, B2, VD, MA se
mantienen apagados. Una vez transcurrido este tiempo, se detiene MM.
Se activa VD, hasta que se activa el sensor “Nivel bajo”, mediante el cual se
cierra VD y se activa MA por espacio de 7.5 segundos, reiniciándose el
proceso nuevamente.
El sistema cuenta con un pulsador de PARE, que al activarse en cualquier
momento detiene todo el proceso, apagando B1, B2, VD, MM y MA, activando
un led rojo y apagando al led verde, indicando que existe una parada del
proceso.
Para reiniciar el proceso nuevamente en donde se quedó al momento de
detenerlo, se debe pulsar “REINICIO”.
PINTURA 1 PINTURA 2
B B
Nivel Alto
Nivel Bajo
M
V
PINTURA PINTURA
LISTA LISTA
M
26. Nomenclaturas:
B1: Bomba 1
B2: Bomba 2
MM: Motor de Mezclado
VD: Válvula de Desagüe
MA: Motor de Avance
4.18. Lecturas complementarias recomendadas.
Para reforzar los conceptos de esta unidad, te recomendamos revisar el libro:
“Microcontroladores PIC” de José María Parejo Usategui. Capítulos III y IV.
(Disponible en la Biblioteca de la Institución)