EE03803C
EE03803C
EE03803C
6 Las interrupciones
6.1 Introducción
Las interrupciones juegan un papel de suma importancia dentro de cualquier sistema basado en
microprocesador o microcontrolador, pues estos deben habitualmente gestionar y controlar distintos
periféricos asociados que, de forma continua, requieren la dedicación de la CPU para llevar a buen
término las tareas que tienen asignadas.
1
Una interrupción la realiza de forma asíncrona un periférico o un dispositivo conectado físicamente al
microcontrolador (figura 6.1), cuando requiere a la CPU el desvío del flujo de ejecución del programa
para gestionar y controlar los diversos sucesos que no se encuentran bajo su supervisión directa. De
esta manera se mejora la eficiencia de la CPU, ya que ésta no tiene que estar continuamente pendiente
de si acontece o no un suceso en un instante de tiempo determinado, y puede realizar otras tareas de
mayor interés, atendiendo a los sucesos tan sólo cuando éstos se producen. Los sucesos acontecidos
pueden ser externos al sistema, como la activación de un nivel lógico o un flanco en un terminal del
microcontrolador, por parte de un periférico, o bien internos, como el desbordamiento de un
temporizador interno del microcontrolador al llegar éste a su máxima capacidad de cuenta.
Módems
Teclado y visualizador
1
Un periférico es un dispositivo conectado al microcontrolador con una función específica. Un periférico puede ser una
impresora, un módem, un teclado alfanumérico, un terminal de vídeo, un sensor, un actuador, etc.
2
Se debe considerar que el microcontrolador puede tener varias fuentes de interrupción, por lo que a cada fuente de
interrupción le corresponde una rutina especifica de RSI.
3
Una puerta de transmisión se realiza con puertas lógicas o bien con transistores bipolares o MOS. Tiene una entrada, una
salida y una línea de control. La activación de la línea de control deja pasar el estado lógico presente en su entrada a su
salida; su desactivación hace que la puerta esté desconectada para evitar que el estado lógico de la entrada pase a la salida.
Generalmente todas las entradas de interrupción suelen tener un bit de habilitación de interrupción
asociado; no obstante, puede haber alguna entrada de interrupción que adolezca de este bit, lo que se
denomina interrupción no mascarable, en cuyo caso el programador no tiene control sobre la
interrupción y la CPU está obligada siempre a atenderla. Las interrupciones no mascarables se
reservan para aquellos periféricos o sucesos de suma importancia, como, por ejemplo, la caída de
tensión de la red eléctrica, en que la CPU dispone de los pocos milisegundos en los que los
condensadores de la fuente de alimentación son capaces de sostener la tensión de alimentación para
salvar los registros que se consideren imprescindibles en una memoria estable, como una memoria
E2PROM o una memoria RAM con una batería externa.
La familia MCS-51 puede llegar a tener hasta siete fuentes de interrupción distintas (figura 6.3), todas
ellas con un bit de habilitación de interrupción situado en el registro IE, Interrupt Enable -dirección
A8H del SFR-, de forma que el programador puede habilitarlas o deshabilitarlas cuando sea necesario.
Respecto a las prioridades, todos los componentes de la familia tienen dos niveles de prioridad que se
determinan con un único bit, para cada entrada de interrupción, situado en el registro IP, Interrupt
Priority -dirección B8H del SFR-, con excepción de las versiones 8XC51Fx y 8XX52/54/58, que
tienen hasta cuatro niveles de prioridad; incorporan, para ello, un segundo registro de prioridad
denominado IPH, Interrupt Priority High -dirección B7H del SFR-. En este último caso, el nivel de
prioridad de una entrada de interrupción se determina mediante sus bits correspondientes de los
registros IP y IPH.
Tres de las seis fuentes de interrupción son externas al microcontrolador: /INT0, /INT1 y el puerto
serie, RI y TI; las fuentes de interrupción restantes son internas y corresponden a los tres
temporizadores, Timer 0, Timer 1 y Timer 2, y al array de contadores programable PCA de la familia
MCS-51. La interrupción de los temporizadores se produce por un desbordamiento en su valor
máximo; entonces se activan los bits de desbordamiento correspondientes: TF0, TF1 o TF2. La
interrupción de la PCA se genera mediante cualquiera de los bits EF, CCF0, CCF1, CCF2, CCF3,
CCF4 y CCF5 del registro CCON, PCA Counter Control Register; cada uno de estos bits de
interrupción tiene asociado un bit de habilitación de interrupción, bits ECF y ECCFn de los registros
CMOD, PCA Counter Mode Register y CCAPMn, PCA Compare/Capture Modules.
El Timer 2 tiene un bit adicional de interrupción, EXF2, que realiza una petición de interrupción si se
detecta un flanco de bajada en el terminal T2 del microcontrolador.
Tal y como muestra la figura 6.3, las interrupciones externas /INT0 y /INT1 se pueden activar tanto
por nivel lógico (cero lógico), como por flanco descendente, mediante la programación de los bits IT0
y IT1 del registro TCON, Timer Control (tabla 6.2), respectivamente. Poner uno de estos bits a cero
lógico hace que la interrupción se active por nivel lógico, mientras que a uno lógico se activa por
flanco descendente.
Registro IE
0 EX0
INT0 IT0 IE0
1
ET0
TF0
0 EX1
INT1 IT1 IE1
1
ET1
TF1
0
CF ECF
1 EC
(†)
0
CCFn ECCFn
1 5
ES
RI
TI
ET2
TF2 (*)
EXF2
EA
Inhibición global
Al producirse una interrupción en una de las entradas externas de interrupción, /INT0 o /INT1, ya sea
por nivel lógico o por flanco descendente, el bit correspondiente, IE0 o IE1 del registro TCON, se
activa a uno lógico, indicando de esta manera que se ha realizado una petición de interrupción, y la
CPU pone en marcha el proceso de atención a la interrupción, siempre y cuando la interrupción esté
habilitada de antemano. En este proceso, los bits IE0 e IE1 se ponen a cero lógico de forma automática
cuando la interrupción se ha activado por flanco descendente. Sin embargo, si la interrupción se ha
activado por nivel lógico, los bits IE0 y IE1 se deben borrar por software dentro de la rutina de RSI.
El estado de las interrupciones externas /INT0 e /INT1 se comprueba una vez cada ciclo máquina, de
forma que la entrada de interrupción, para el caso de que esté activada por flanco descendente, se debe
sostener a nivel lógico alto al menos un ciclo máquina, y sostener a nivel lógico bajo al menos otro
ciclo máquina más, para que el flanco descendente sea detectado y se active el bit IE0 o IE1,
correspondiente. En el caso de que la interrupción esté activada por nivel lógico, la entrada de
interrupción se debe sostener a nivel lógico bajo al menos durante 1 ciclo máquina, para que la
interrupción sea detectada por la CPU.
En las interrupciones internas producidas por los temporizadores Timer 0 o Timer 1, se activan los bits
TF0 o TF1, según corresponda, del registro TCON a uno lógico, al realizar la petición de interrupción.
Estos bits se mantienen en este estado hasta que la CPU atiende la petición, momento en el cual los
pone a cero lógico de forma automática.
El temporizador Timer 2 puede producir una interrupción a través de la activación a uno lógico de los
bits TF2 o EXF2. Estos bits no se ponen a cero lógico de manera automática, sino que los debe poner
el programador por software.
Las interrupciones producidas por el puerto serie activan a uno lógico los bits TI o RI del registro
SCON, cuando el microcontrolador transmite un dato o cuando recibe un dato, respectivamente. Estos
bits los debe poner a cero lógico el programador mediante software.
La tabla 6.1 muestra los bits de petición de interrupción asociados a cada una de las fuentes de
interrupción.
Tabla 6.1 Fuentes de interrupción, bits activados y tabla de vectores de salto para la MCS-51
Bit Comentario
TF1 Bit de rebasamiento del Timer 1. Se pone a 1 por hardware en el rebasamiento. La CPU lo pone a 0 cuando
procesa la interrupción y salta a la rutina de RSI.
TR1 Bit de marcha/paro del Timer 1. Se pone a 1 ó 0 por software para poner en marcha o parar el Timer 1
TF0 Bit de rebasamiento del Timer 0. Se pone a 1 por hardware en el rebasamiento. La CPU lo pone a 0 cuando
procesa la interrupción y salta a la rutina de RSI.
TR0 Bit de marcha/paro del Timer 1. Se pone a 1 ó 0 por software para poner en marcha o parar el Timer 1
IE1 Bit de interrupción del terminal /INT1. Se pone a 1 en una petición de interrupción, se pone a 0 por
hardware si /INT1 está activada por flanco descendente.
IT1 Bit de selección de interrupción por nivel o por flanco descendente de /INT1. A 0 la interrupción se activa
por nivel, a 1 se activa por flanco descendente.
IE0 Bit de interrupción del terminal /INT0. Se pone a 1 en una petición de interrupción, se pone a 0 por
hardware si /INT0 está activada por flanco descendente.
IT0 Bit de selección de interrupción por nivel o por flanco descendente de /INT0. A 0 la interrupción se activa
por nivel, a 1 se activa por flanco descendente.
En la tabla 6.1 también se observa que el espacio existente entre los vectores de interrupción es de tan
sólo 8 bytes. Este espacio suele ser insuficiente para albergar una rutina de RSI, por lo que, en estas
posiciones, se suele insertar una instrucción de salto, LJMP, AJMP o SJMP, hacia la rutina de RSI que
atienda a la interrupción; así, se puede situar esta rutina en cualquier zona del espacio de memoria
disponible por el microcontrolador.
El retorno de una rutina de RSI se debe realizar con la instrucción RETI, para que la CPU diferencie
este retorno, del retorno de subrutina (instrucción RET).
;**************************************************************
;Vectorización de interrupciones
;**************************************************************
ORG 03H ;Posiciona la instrucción siguiente en 03H
LJMP RSI_INT0 ;Salto a la rutina de RSI
ORG 0BH ;Posiciona instrucción siguiente en 0BH
LJMP RSI_TIMER0 ;Salto a la rutina de RSI
ORG 013H ;Posiciona instrucción siguiente en 013H
LJMP RSI_INT1 ;Salto a la rutina de RSI
RSI_INT0: MOV ..... ;Rutina de RSI para /INT0
:
RETI
RSI_TIMER0: MOV ..... ;Rutina de RSI para TIMER0
:
RETI
La estructura del programa cuando se utilizan interrupciones estará formada por una rutina de
vectorización, como la mostrada en este apartado. El registro PC se inicializa a 0000H tras un reset o
la puesta en marcha del microcontrolador, por lo que la primera instrucción que se ejecuta es la
contenida en la dirección 0000H. La estructura de un programa, también, en general contempla una
rutina “Inicio”, donde se determinan los valores de las variables que se van a utilizar y el modo de
operar del microcontrolador, y una rutina “Principal”, donde se llevan a cabo la mayor parte de las
tareas que debe gestionar la CPU, aunque, parte de estas tareas puedan solventarse mediante
interrupciones. En conclusión, la rutina de vectorización anterior debe, además, incluir en la dirección
0000H una instrucción de salto hacia la rutina “Inicio”, tal y como se muestra en la rutina siguiente:
;****************************************************
;Vectorización de interrupciones
;****************************************************
ORG 0H
LJMP Inicio ;Salto a la rutina Inicio
ORG 03H
LJMP RSI_INT0
ORG 0BH
LJMP RSI_TIMER0
ORG 013H
LJMP RSI_INT1
La mayor parte de los componentes de la MCS-51 tienen dos niveles de prioridad, con excepción de
las versiones 8XC51Fx y 8XC52/54/58, que tienen hasta cuatro niveles de prioridad. El nivel de
prioridad se determina con el registro de prioridades IP, Interrupt Priority, del área de SFR (tabla 6.4).
Poniendo un bit de este registro a uno lógico se fija la prioridad a nivel alto y a cero lógico se fija a
nivel bajo.
Para el caso de que dos o más interrupciones tengan el mismo nivel de prioridad y se produzca una
petición simultánea de interrupción, el fabricante asigna un nivel de prioridad por defecto a cada una
de las fuentes de interrupción del microcontrolador (tabla 6.5), de forma que en una petición
simultánea de interrupción, la CPU atienda primero a la interrupción con mayor prioridad según la
tabla 6.5.
BIT COMENTARIO
EX0 EX0 = 1 habilita la interrupción en INT0. EX0 = 0 la inhabilita
ET0 ET0 = 1 habilita la interrupción del Timer 0. ET0 = 0 la inhabilita.
EX1 EX1 = 1 habilita la interrupción en INT1. EX1 = 0 la inhabilita.
ET1 ET1 = 1 habilita la interrupción del Timer 1. ET1 = 0 la inhabilita.
ES ES = 1 habilita la interrupción del puerto serie. ES = 0 la
inhabilita.
ET2* ET2 = 1 habilita la interrupción del Timer 2. ET2 = 0 la inhabilita.
EC† EC =1 habilita la interrupción de la PCA. EC = 0 la inhabilita.
EA EA = 1 permite todas las habilitaciones o inhabilitaciones anteriores.
EA = 0 no reconoce ninguna interrupción.
* En las versiones con 3 temporizadores
†
En las versiones con PCA
BIT COMENTARIO
PX0 Bit de prioridad de /INT0.
PT0 Bit de prioridad del Timer 0.
PX1 Bit de prioridad de /INT1.
PT1 Bit de prioridad del Timer 1
PS Bit de prioridad del puerto serie.
PT2* Bit de prioridad del Timer 2.
PPC† Bit de prioridad de la PCA.
- Bit reservado.
* En las versiones con 3 temporizadores
†
En las versiones con PCA
Prioridad Fuente
(más alta).......1 /INT0
2 Timer 0
3 /INT1
4 Timer 1
5 PCA†
6 Puerto Serie
(más baja).......7 Timer 2*
* En las versiones con 3 temporizadores
†
En las versiones con PCA
Las versiones 8XC51Fx y 8XC52/54/58 tienen cuatro niveles de prioridad que se determinan por
medio de los registros IP y IPH (tabla 6.6). En la tabla 6.7 se indica el nivel de prioridad según el
estado de los bits correspondientes a cada una de las fuentes de interrupción.
Tabla 6.6 Registro de prioridades IPH para las versiones 8XX52/54/58 y 8XC51Fx de la MCS-51
(MSB) Registro IPH (LSB)
PPCH † PT2H* PSH PT1H PX1H PT0H PX0H
BIT COMENTARIO
PX0H Bit alto de prioridad de /INT0.
PT0H Bit alto de prioridad del Timer 0.
PX1H Bit alto de prioridad de /INT1.
PT1H Bit alto de prioridad del Timer 1.
PSH Bit alto de prioridad del puerto serie.
PT2H Bit alto de prioridad del Timer 2.
PPCH† Bit alto de prioridad de la PCA.
- Bit reservado.
†
Sólo en las versiones 8XC51Fx.
Tabla 6.7 Niveles de prioridad para las versiones 8XX52/54/58 y 8XC51Fx de la MCS-51
Bits de prioridad Nivel de prioridad
IPH.x IP.x
0 0 Nivel 0 (Menor)
0 1 Nivel 1
1 0 Nivel 2
1 1 Nivel 3 (Mayor)
La CPU reconoce la petición de una interrupción cuando vectoriza la interrupción, es decir, cuando
salta a la rutina de RSI correspondiente. Según el tipo de interrupción, la CPU, además, borra el bit
activado en la petición de interrupción (tabla 6.1), como es el caso de los bits TF0 y TF1, o de los bits
IE0 e IE1, sólo cuando la interrupción ha sido activada por flanco descendente. En otros casos el bit
activado por la interrupción se debe borrar por software.
S5P2 S6
Comprobación de
Consulta de Salto a la Rutina de
interrupciones
interrupciones rutina de RSI RSI
activas
Fig. 6.4 Diagrama de tiempos del salto a la rutina de RSI en el proceso de interrupciones
La CPU guarda en la memoria interna de la pila el contenido del registro PC (dos bytes) y, luego, salta
a la rutina RSI correspondiente. La CPU ejecuta la rutina de RSI hasta que encuentra una instrucción
RETI, que le indica que se ha llegado al final del proceso de interrupción; recupera entonces los dos
bytes almacenados en la pila y los asigna al registro PC, por lo que la ejecución del programa regresa
al punto de partida donde se inició la interrupción.
El tiempo transcurrido (figura 6.4), desde que se produce la interrupción (S5P2 del ciclo C1), hasta
que la CPU comienza a ejecutar la rutina de RSI (ciclo C5), es de como mínimo tres ciclos máquina.
El tiempo de respuesta es mayor si el salto resulta abortado por una de las condiciones mencionadas.
En el primer caso, si una interrupción de mayor o igual prioridad está en proceso, el tiempo de espera
dependerá de la rutina de RSI en ejecución. En el segundo caso, cuando la CPU debe esperar a que se
4
finalice la ejecución de la instrucción actual, el tiempo de espera, en el peor caso , no puede ser
superior a tres ciclos máquina. En el tercer caso, si una instrucción RETI, o la escritura del registro IE
o IP, está en progreso, el tiempo adicional de espera no puede ser superior a cinco ciclos máquina. En
definitiva, el tiempo de respuesta de una interrupción estará comprendido entre tres y nueve ciclos
máquina.
Se conectan cuatro teclas al puerto P1 de un microcontrolador 80C31 (figura 6.5). Las entradas
del puerto P1 tienen una resistencia interna de pull-up (figura 3.4), por lo que un terminal del
puerto, por ejemplo P1.0, estará en el estado 1 lógico (Vcc) cuando no se pulsa la tecla T1, y a
0 lógico (masa) cuando se pulsa T1. Luego, la detección de si una tecla ha sido pulsada o no,
consiste en leer el estado lógico del puerto P1, y ver si hay algún cero en una de sus patillas. En
la figura 6.5 cada una de las teclas está conectada a una puerta AND, de manera que la
pulsación de cualquiera de las cuatro teclas causará un 0 lógico en la entrada de interrupción
/INT0, y provocará una interrupción en el caso de que esté habilitada.
4
El peor caso corresponde a las instrucciones MUL y DIV que tardan en ejecutarse cuatro ciclos máquina.
T1 P1.0
T2
P1.1
T3
P1.2
T4 P1.3
80C31
/INT0
En este ejemplo se debe habilitar la interrupción /INT0 y crear una rutina RSI capaz de detectar
la tecla que ha sido pulsada. Para ello, se utilizará el registro B como registro indicador de la
pulsación de una tecla, y se le asignará el valor 00H cuando no se haya pulsado ninguna tecla, y
los valores 01H, 02H, 03H y 04H, cuando se pulsen las teclas T1, T2, T3 y T4,
respectivamente. La interrupción /INT0, en este ejemplo, se establecerá por nivel lógico (bit
IT0 del registro TCON a 0 lógico). Se debe tener en cuenta que todos los bits accesibles de los
registros TCON, IE y IP quedan a 0 lógico tras un reset del microcontrolador.
;**********************************************************************
; Rutina de vectorización (ejemplo 6.1)
;**********************************************************************
ORG 0H
LJMP Inicio
ORG 03H
LJMP RSI_INT0
;**********************************************************************
; Rutina de Inicio. (Se habilita las interrupciones y /INT0 por flanco descendente)
;**********************************************************************
Inicio: SETB PX0 ;Prioridad alta para la interrupción /INT0 (Registro IP)
SETB EX0 ;Activa el bit de habilitación de /INT0 (Registro IE)
SETB EA ;Activa el bit de habilitación general (Registro IE)
LJMP Principal
;**********************************************************************
; Programa Principal
;**********************************************************************
ORG 0300H
Principal: SJMP Principal ;Bucle infinito sin propósito definido
;**********************************************************************
; Rutina de RSI de /INT0
;**********************************************************************
RSI_INT0: JNB P1.0, Tecla_1 ;¿Es la tecla T1?
JNB P1.1, Tecla_2 ;¿Es la tecla T2?
JNB P1.2, Tecla_3 ;¿Es la tecla T3?
SJMP Tecla_4 ;Si no es ninguna de las anteriores, es la tecla T4
Tecla_1: MOV B, #01H ;Pone 01H en el registro B
SJMP Salir ;Ir a Salir
Tecla_2: MOV B, #02H ;Pone 02H en el registro B
SJMP Salir ;Ir a Salir
Tecla_3: MOV B, #03H ;Pone 03H en el registro B
SJMP Salir ;Ir a Salir
Tecla_4: MOV B, #04H ;Pone 04H en el registro B
Salir: CLR IE0 ;Se pone a cero para que /INT0 pueda interrumpir de nuevo.
RETI ;Final de interrupción
La ejecución de las instrucciones del programa empieza por la dirección 0H, pues, en la puesta
en marcha del microcontrolador, se ejecuta un reset interno que sitúa el registro PC a 00H. La
primera instrucción, entonces, es una instrucción de salto a la rutina “Inicio”, donde se
configura la forma de operar de la interrupción /INT0, mediante los registros TCON, IE y IP.
De esta rutina, la CPU pasa a ejecutar la rutina “Principal”, que sólo consiste en un bucle
infinito, sin ningún objetivo específico. Esto es así, por el funcionamiento casi exclusivo del
programa mediante interrupciones, de manera que la CPU está siempre ejecutando
instrucciones de la rutina “Principal”, a la espera de que las interrupciones se produzcan, lo que
causa el salto automático hacia las rutinas de RSI.
En el momento que se pulsa una tecla, se provoca la interrupción /INT0 y se ejecuta la rutina
“RSI_INT0”. Esta rutina comprueba de forma secuencial, mediante la instrucción JNB, cuál ha
sido la tecla pulsada, colocando en el registro B el valor adecuado, según los objetivos
marcados en este ejemplo. Al final de la rutina, el bit IE0, debido a que la interrupción /INT0
se ha habilitado por nivel lógico, se borrará por software para que se produzca una nueva
interrupción en /INT0.
La lectura de las teclas, en el programa realizado, se hace de manera secuencial, por lo que el
programa es incapaz de detectar una pulsación simultánea de varias teclas, y da por válida la
tecla que lee primero; es decir, en el caso de pulsarse las teclas conectadas T1 y T2, en el
registro B se colocaría el código correspondiente a la tecla T1. Este problema se solventa en el
siguiente ejemplo que consiste en una modificación del actual.
En la figura 6.6 se emplea el circuito integrado 7405 que contiene hasta 6 puertas inversoras en
colector abierto. La puerta inversora está formada por un único transistor, del cual se dispone
de su colector, tal y como se ve en el detalle de la figura. La puerta inversora puede soportar
una corriente máxima de 25mA, valor más que suficiente para encender de manera adecuada el
diodo LED que tiene asociado.
/INT0
T5
/INT1
;************************************************************************
;Rutina de vectorización (ejemplo 6.2)
;************************************************************************
ORG 0H
LJMP Inicio
ORG 03H
LJMP RSI_INT0
ORG 013H
LJMP RSI_INT1
;************************************************************************
; Rutina de Inicio
; Se habilita las interrupciones y /INT0 por flanco descendente
;************************************************************************
Inicio: SETB IT1 ;Interrupción /INT1 activa por flanco descendente
SETB PX1 ;Prioridad alta para /INT1
SETB EX0 ;Activa el bit de habilitación de /INT0
SETB EX1 ;Activa el bit de habilitación /INT1
SETB EA ;Activa el bit de habilitación general
;************************************************************************
; Programa Principal
;************************************************************************
Principal: MOV A, B ;Lee el registro B
CALL Siete_seg ;Codifica en 7 segmentos para mostrar en dígito
MOV P2, A ;Carga en dígito
SJMP Principal ;Bucle infinito a Principal
Siete_seg: INC A
MOVC A, @A+PC
RET
DB 0000 0000b ;Todos los leds apagados
DB 0000 0110b ;leds b y c encendidos, caracter 1, tecla T1
DB 0101 1011b ;leds a, b, d, e y g encendidos, caracter 2, tecla T2
DB 0100 1111b ;leds a, b, c, d y g encendidos, caracter 3, tecla T3
DB 0110 0110b ;leds b, c, f y g encendidos, caracter 4, tecla T4
DB 1111 1111b ;Todos los leds encendidos, varias teclas pulsadas
;************************************************************************
; Rutina de RSI de /INT0
;************************************************************************
RSI_INT0: MOV A,P1 ;Lee el puerto P1
ORL A,#F0H ;Máscara, fuerza los 4 bits altos de P1 a 1 lógico
CJNE A, #11111110b, Dif_1 ;¿Es tecla T1?
MOV B, #01H ;Pone 01H en el registro B
SJMP Salir ;Ir a Salir
Dif_1: CJNE A, #11111101b, Dif_2
MOV B, #02H ;Pone 02H en el registro B
SJMP Salir ;Ir a Salir
Dif_2: CJNE A, #11111011b, Dif_3
MOV B, #03H ;Pone 03H en el registro B
SJMP Salir ;Ir a Salir
Dif_3: CJNE A, #11110111b, Varias_tec
MOV B, #04H ;Pone 04H en el registro B
SJMP Salir ;Ir a Salir
Varias_tec: MOV B, #05H ;Pone 05H en el registro B
Salir: CLR IE0 ;Se pone a cero para que /INT0 pueda interrumpir de nuevo.
RETI ;Final de interrupción
;************************************************************************
; Rutina de RSI de /INT1
;************************************************************************
RSI_INT1: MOV B, #0 ;Borra el registro B
RETI ;No es necesario borrar el bit IE1, ya que es por flanco
La rutina “Principal” de este ejemplo se encarga de leer el contenido del registro B y de poner
en el dígito el carácter correspondiente según sea el valor de B. El registro B puede valer 00H
al principio, si no se ha pulsado ninguna tecla, o tras pulsar la tecla T5; puede valer 01H, 02H,
03H o 04H, al pulsar las teclas T1, T2, T3 o T4, respectivamente; y puede valer 05H en el caso
de que se pulsen varias teclas al mismo tiempo. Con el valor del registro B se lee la tabla
“Siete_seg”, que proporciona el código en siete segmentos, correspondiente al carácter que se
quiere mostrar en el dígito del ejemplo. De todas formas, la tabla “Siete_seg” se puede suprimir
colocando en el registro B, directamente, el código del carácter que deberá mostrar en el dígito,
según sea el caso.
El 74LS148 es un circuito integrado codificador con prioridad que se puede emplear para
conectar varios periféricos a una misma línea de interrupción, o bien, como en este caso, a la
conexión de hasta 8 teclas al microcontrolador, empleando para ello el sistema de
interrupciones.
Según el circuito de la figura 6.7, el codificador con prioridad codifica en binario la tecla
pulsada, sacando el código por las tres líneas de salida: A1, A2 y A3. Con el 74LS148, si se
pulsan varias teclas a la vez, aparece a su salida el código correspondiente a la entrada con
mayor prioridad (la entrada 7 es la de mayor prioridad, y la entrada 0 la de menor prioridad).
Cuando se pulsa una tecla la línea de salida /GS del codificador se pone a cero lógico, de
manera que puede generar una interrupción conectándola a la entrada /INT0 del
microcontrolador. La entrada /EI del 74LS148 es de habilitación del circuito integrado.
/EI se conecta directamente a masa para que el codificador esté siempre habilitado. La tabla de
verdad del codificador se puede ver en la tabla 6.15.
87C51 7405 Ánodo común
74LS148 R Vcc
T1 P1.0 a a
0 A1 P2.0
T2 1 b
A2 P1.1 P2.1 f b
T3 2 A3 P1.2 g
T4 3 T9 e c
T5 DP
4 P1.4 P2.7
T6 d DP
5
T7 6
T8 7 /GS /INT0
/EI
;************************************************************************
; Rutina de RSI de /INT0
;************************************************************************
ORG 0400H
RSI_INT0: MOV A,P1 ;Lee el puerto P1
ANL A,#07H ;Máscara, fuerza P1 a 0, excepto P1.0, P1.1 y P1.2
CALL Tecla_in ;Ejecuta subrutina Tecla_in
MOV B,A ;Guarda código en B
CLR A ;Borra A
CLR IE0 ;Borra bit IE0, para una posterior interrupción
RETI ;Retorno de interrupción
Tecla_in: INC A
MOVC A,@A+PC
RET
DB 0111 1111b ;leds a, b, c, d, e, f y g encendidos, caracter 8, tecla T8
DB 0000 0111b ;leds a, b y c encendidos, caracter 7, tecla T7
DB 0111 1101b ;leds a, c, d, e, f y g encendidos, caracter 6, tecla T6
DB 0110 1101b ;leds a, c, d, f, y g encendidos, caracter 5, tecla T5
DB 0110 0110b ;leds b, c, f y g encendidos, caracter 4, tecla T4
DB 0100 1111b ;leds a, b, c, d y g encendidos, caracter 3, tecla T3
DB 0101 1011b ;leds a, b, d, e y g encendidos, caracter 2, tecla T2
DB 0000 0110b ;leds b y c encendidos, caracter 1, tecla T1
La rutina de RSI de /INT0 lee directamente el valor del puerto P1, aplica una máscara al valor
leído, puesto que sólo interesa el valor de las patillas P1.0, P1.1 y P1.2 del puerto, y pone el
código del carácter en siete segmentos, correspondiente a la tecla pulsada, en el registro B. La
rutina “Principal” comprueba el estado de la tecla T9 con la instrucción “JB P1.4, Rut_ok”, y
sitúa el valor del registro B, procedente de la rutina “RSI_INT0”, en el puerto P2, para su
visualización. El registro B se pone a cero cuando se pulsa la tecla T9.
Las interrupciones pueden ocurrir como resultado de la actividad interna del µC (por ejemplo el
rebasamiento de un Timer) o por la activación de señales eléctricas externas al µC, como, por ejemplo,
la recepción de un dato por el puerto de comunicación serie. Las interrupciones pueden ser habilitadas
o inhibidas individualmente, excepto la instrucción TRAP, y pueden programarse en uno de cuatro
niveles de prioridad.
Cada fuente de interrupción (excepto la instrucción TRAP) dispone de uno o varios flags, o banderas
de petición de interrupción, que pueden ser activados por programa o por hardware; su nivel activo es
uno lógico.
INT0 INT1
8XC251Sx
Timer 0
Timer 1
Controlador de
CPU
interrupciones
Timer 2
Instrucción Puerto
PCA
TRAP serie
Tiempo de respuesta
Oscilador
Estados
Petición
interrupción
externa
Finalización de la instrucción en curso Push PC Call ISR RSI
Fig. 6.9 Proceso de atención a una interrupción externa
Cada una de las fuentes de interrupción de la familia MCS-251 tiene asociada una dirección diferente
de comienzo de la RSI, denominada vector de interrupción. En la tabla 6.9 están indicados los
vectores de interrupción para cada una de las fuentes de interrupción.
Tabla 6.9 Vectores de interrupción
La rutina de servicio a la interrupción finaliza con la instrucción RETI. La función de esta instrucción
es la de indicar a la CPU que ha sido completada la ejecución de la RSI y extraer de la pila la
dirección de retorno y colocarla en el PC.
Cabe destacar, según la tabla 6.8, que entre la dirección de comienzo de la RSI de una fuente de
interrupción y la siguiente hay tan sólo ocho posiciones de memoria, que en la mayoría de los casos es
insuficiente para albergar la RSI. Por este motivo, si se utilizan interrupciones consecutivas, por
ejemplo /INT0 y Timer 0, la RSI deberá comenzar con un salto incondicional hacia una dirección de
memoria situada en una zona del espacio de memoria disponible para almacenar las instrucciones de la
RSI. A continuación se presenta, a modo de ejemplo, un listado de instrucciones cuya función es
reubicar la localización de las RSI de las fuentes de interrupción del Timer 0, Timer 1 y PCA.
;******************************************************************************************
; REUBICACION DE LAS RSI DE LAS FUENTES DE INTERRUPCION Timer 0, Timer 1 y PCA
;******************************************************************************************
RSI _TIMER0 EQU 2000H ; Dirección de comienzo de la RSI del Timer 0
RSI _TIMER1 EQU 2200H ; Dirección de comienzo de la RSI del Timer 1
RSI _PCA EQU 2400H ; Dirección de comienzo de la RSI del PCA
ORG FF:000BH ; Vector de interrupción del Timer 0
JMP RSI_TIMER0
Cada una de las fuentes de interrupción de los microcontroladores de la familia MCS-251, con
excepción de la instrucción TRAP, puede ser individualmente habilitada o inhibida poniendo a uno o a
cero lógico el bit correspondiente del registro de habilitación de interrupciones IE0. Este registro está
ubicado en el área de registros de función específica, SFR, en la dirección S:0A8H. En la tabla 6.10
aparecen los bits que componen el registro IE0. Cabe destacar que este registro contiene un bit de
habilitación global de interrupciones: EA. Si EA está a uno lógico, las interrupciones pueden ser
habilitadas o inhibidas individualmente por los bits del registro IE0. Si EA está a cero lógico, todas las
interrupciones, excepto la TRAP, estarán inhibidas.
Tabla 6.10 Registro habilitador de interrupciones IE0
IE0 Dirección: S:0A8H Valor de reset: 0000 0000b
b7 b6 b5 b4 b3 b2 b1 b0
EA EC ET2 ES ET1 EX1 ET0 EX0
Número Nombre
Función
de bit del bit
7 EA Bit de habilitación general de interrupciones:
poniendo a uno lógico este bit se habilitan todas las interrupciones que están
individualmente habilitadas por los bits 0-6. Poniendo a cero este bit se inhiben
todas las interrupciones excepto la interrupción TRAP, que no puede inhibirse.
6 EC Bit de habilitación de la interrupción del PCA:
poniendo a uno lógico este bit se habilita la interrupción del PCA.
5 ET2 Bit de habilitación de la interrupción del Timer 2:
poniendo a uno lógico este bit se habilita la interrupción del Timer 2.
4 ES Bit de habilitación de la interrupción del puerto serie :
poniendo a uno lógico este bit se habilita la interrupción del puerto serie.
3 ET1 Bit de habilitación de la interrupción del Timer 1:
poniendo a uno lógico este bit se habilita la interrupción del Timer 1.
2 EX1 Bit de habilitación de la interrupción externa 1:
poniendo a uno lógico este bit se habilita la interrupción externa 1.
1 ET0 Bit de habilitación de la interrupción del Timer 0:
poniendo a uno lógico este bit se habilita la interrupción del Timer 0.
0 EX0 Bit de habilitación de la interrupción externa 0:
poniendo a uno lógico este bit se habilita la interrupción externa 0.
Cada una de las siete fuentes de interrupción de la familia MCS-251 puede programarse
individualmente en uno de cuatro niveles de prioridad. La programación de los niveles de prioridad
permite establecer el orden en que se deben atender las interrupciones en caso de una activación
simultánea.
El establecimiento de las prioridades se consigue poniendo a uno o cero lógico el bit correspondiente
en dos registros de prioridad de interrupciones: Interrupt Priority High Register, IPH0, e Interrupt
Priority Low Register, IPL0 (tablas 6.11 y 6.12 respectivamente). Por tanto, cada fuente de
interrupción tiene asociados dos bits de programación de prioridad, un bit en el registro IPH0 y otro en
el registro IPL0. El bit ubicado en el registro IPH0 es el bit más significativo (MSB), mientras que el
bit ubicado en el registro IPL0 es el bit menos significativo (LSB). El valor de estos dos bits define el
nivel de prioridad de la fuente de interrupción. Los niveles posibles son cuatro: nivel 0, 1, 2 o 3: el
nivel 0 es el de menor prioridad y el nivel 3 el de mayor prioridad (tabla 6.13).
Número Nombre
Función
de bit del bit
7 --- Reservado.
6 IPH.6 Bit alto de prioridad de interrupción del PCA.
5 IPH.5 Bit alto de prioridad de interrupción del Timer 2.
4 IPH.4 Bit alto de prioridad de interrupción del puerto serie.
3 IPH.3 Bit alto de prioridad de interrupción del Timer 1.
2 IPH.2 Bit alto de prioridad de la interrupción externa 1, /INT1.
1 IPH.1 Bit alto de prioridad de interrupción del Timer 0.
0 IPH.0 Bit alto de prioridad de la interrupción externa 0, /INT0.
Número Nombre
Función
de bit del bit
7 --- Reservado.
6 IPL.6 Bit bajo de prioridad de interrupción del PCA.
5 IPL.5 Bit bajo de prioridad de interrupción del Timer 2.
4 IPL.4 Bit bajo de prioridad de interrupción del Puerto Serie.
3 IPL.3 Bit bajo de prioridad de interrupción del Timer 1.
2 IPL.2 Bit bajo de prioridad de la interrupción externa 1, /INT1.
1 IPL.1 Bit bajo de prioridad de interrupción del Timer 0.
0 IPL.0 Bit bajo de prioridad de la interrupción externa 0, /INT0.
El funcionamiento del mecanismo de niveles de prioridad está sujeto a unas reglas muy sencillas:
1. Una interrupción programada en un nivel bajo puede ser interrumpida por una
interrupción programada en un nivel de prioridad mayor, pero no por una interrupción de
nivel igual o menor.
2. Si una interrupción está programada en el nivel tres no podrá ser interrumpida por
ninguna fuente de interrupción.
3. Si dos o más interrupciones se activan al mismo tiempo la CPU atenderá en primer lugar a
la interrupción de mayor nivel de prioridad. Una vez ejecutada la rutina de la interrupción
más prioritaria, la CPU atenderá al resto de fuentes de interrupción siguiendo un orden
decreciente de prioridades.
4. Si se reciben peticiones de interrupción simultáneas correspondientes a fuentes
programadas en un mismo nivel de prioridad, el orden de respuesta seguirá una secuencia
preestablecida indicada en la tabla 6.14.
Para realizar esta asignación de niveles de prioridad se deben programar los registros de
prioridad de interrupción con los siguientes valores: IPH0 = 16H (0001 0110), IPL0 = 42H
(0100 0010).
Si en estas condiciones se produce en primer lugar una petición de interrupción del PCA, la
CPU pasará a ejecutar la RSI del PCA. Si mientras se ejecuta la RSI del PCA, ocurre una
petición simultánea de interrupción de las fuentes /INT1 y puerto serie, la CPU dejará de
ejecutar la RSI del PCA para ejecutar las RSI de las interrupciones que se han activado, dado
que poseen un nivel de prioridad mayor.
Las interrupciones /INT1 y puerto serie poseen el mismo nivel de prioridad pero, teniendo en
cuenta el orden establecido en la tabla 6.14, se ejecutará primero la RSI de la interrupción
/INT1 y, a continuación, la RSI del puerto serie.
Si, por ejemplo, se activa la interrupción Timer 0 mientras se está ejecutando la RSI del puerto
serie, la CPU pasa a ejecutar la RSI del Timer 0, porque posee un nivel de prioridad mayor que
el puerto serie. Una vez ejecutada la RSI del Timer 0, la CPU finalizará la ejecución de la RSI
del puerto serie y, a continuación, acabará de ejecutar la RSI del PCA para, finalmente,
continuar ejecutando el programa “Principal”. En la figura 6.10 se representa, de forma
esquemática, la secuencia que sigue la CPU en la atención a las distintas fuentes de
interrupción de este ejemplo.
PROGRAMA
PRINCIPAL RSI_/INT1
RSI_PCA
RETI Int. T0
RETI RETI
Fig. 6.10 Esquema de la secuencia de atención a las interrupciones del ejemplo 6.4
Las interrupciones /INT0 e /INT1 posibilitan el control de periféricos externos mediante el mecanismo
de interrupciones. En la figura 6.11 está representada, a modo de ejemplo, la conexión de dos
periféricos externos a las entradas de interrupción /INT0 e /INT1.
Las interrupciones externas /INT0 e /INT1 se pueden programar para ser activas por flanco
descendente o por nivel bajo, dependiendo del valor de los bits IT0 e IT1 del registro TCON. Con el
bit IT0 a cero lógico, la interrupción /INT0 se activa por nivel, mientras que con IT0 a uno lógico, la
interrupción /INT0 se activa por flanco descendente. La misma relación se produce entre el bit IT1 y
la interrupción /INT1.
Cuando se genera una interrupción externa del tipo /INT0 o /INT1, se activa el correspondiente flag
de petición de interrupción, bits IE0 o IE1, del registro TCON (tabla 6.15). Si la interrupción se ha
activado por flanco descendente, los flags de petición de interrupción se borran por hardware cuando
la CPU salta a la rutina de atención a la interrupción para proceder a su ejecución. Si la interrupción se
activa por nivel, el flag de interrupción se deberá borrar mediante una instrucción dentro de la RSI.
Para este caso, la causa que ha generado la interrupción externa /INT0 o /INT1 debe desactivarse
antes de que acabe la RSI o se generará una nueva petición de interrupción.
8XC251
Periférico 1
INT0 INT
(P3.2)
Periférico 2
INT1
(P3.3) INT
Fig. 6.11 Conexión de periféricos externos a las entradas de interrupción del µC 8XC251Sx
Para detectar la petición de interrupción, la CPU lee el estado de los pines asociados a las
interrupciones externas /INT0 e /INT1 una vez cada ocho períodos de reloj. Tanto si la interrupción
externa está programada por nivel como por flanco, será necesario mantener un nivel bajo durante al
menos diez períodos para garantizar la detección de la interrupción.
Tabla 6.15 Interrupciones externas
Fuente de interrupción Flag Bit de configuración por flanco o nivel Vector de interrupción
/INT0 IE0 IT0 FF:0003H
/INT1 IE1 IT1 FF:0013H
Si la aplicación diseñada requiere el control de más de dos periféricos externos, se deberá incluir en el
diseño algún sistema, hardware y/o software, que permita determinar qué periférico o periféricos han
interrumpido, y en el caso que haya interrumpido más de uno, en qué orden se deben atender.
Periférico 7 INT
74LS148 8XC251
Periférico 6 INT
7
6
Periférico 5 INT
5
A1 P1.0
Periférico 4 INT 4
A2 P1.1
3
A3 P1.2
Periférico 3 INT 2
1
GS INT0
Periférico 2 INT
0 EO
Periférico 1 INT E1
Periférico 0 INT
Si uno o varios periféricos activan las entradas del codificador 74LS148, éste pondrá a cero su
salida /GS, y se realizará una petición de interrupción al µC 8XC251Sx a través de la entrada
/INT0. Al mismo tiempo, en las salidas de datos A2, A1 y A0, aparece la combinación binaria
correspondiente a la entrada activa de mayor peso. Por tanto, la prioridad en la atención a los
periféricos se establece mediante el orden en que se conectan éstos a las entradas del
codificador, de forma que el periférico que está conectado a la entrada siete es el de mayor
prioridad, y el que está conectado a la entrada cero el de menor prioridad.
Por otro lado, se debe establecer una tabla de vectores de salto, donde se adjudique una
dirección de comienzo de la RSI de cada uno de los periféricos (tabla 6.17). Lógicamente, las
rutinas de atención a los periféricos se deben colocar en zonas de memoria que no se utilicen
para otro fin.
;***********************************************************************************
; RUTINA DE SERVICIO A LA INTERRUPCION INT0
;***********************************************************************************
ORG FF:0003H
JMP SRI_INT0 ; La RSI comienza en la dirección FF:1000H para tener más espacio de memoria.
ORG FF:1000H
SRI_INT0: MOV A,P1 ; Se lee la combinación binaria que proporciona el codificador.
ANL A,#07H ; Unicamente se toman los 3 bits significativos de P1.
RL A ; Se multiplica por dos.
MOV DPTR,#JMP_TBL ; En función de la combinación leída se salta a la rutina
JMP @A+DPTR ; que atiende al periférico que ha interrumpido.
JMP_TBL: AJMP RUT7 ; Salto a la rutina que atiende al periférico siete.
AJMP RUT6 ; Salto a la rutina que atiende al periférico seis.
AJMP RUT5 ; Salto a la rutina que atiende al periférico cinco.
AJMP RUT4 ; Salto a la rutina que atiende al periférico cuatro.
AJMP RUT3 ; Salto a la rutina que atiende al periférico tres.
AJMP RUT2 ; Salto a la rutina que atiende al periférico dos.
AJMP RUT1 ; Salto a la rutina que atiende al periférico uno.
AJMP RUT0 ; Salto a la rutina que atiende al periférico cero.
ORG FF:1100H
RUT7: ; Instrucciones de la rutina que atiende al periférico siete.
........
RETI
ORG FF:1180H
RUT6: ; Instrucciones de la rutina que atiende al periférico seis.
........
RETI
ORG FF:1200H
RUT5: ; Instrucciones de la rutina que atiende al periférico cinco.
........
RETI
ORG FF:1280H
RUT4: ; Instrucciones de la rutina que atiende al periférico cuatro.
........
RETI
ORG FF:1300H
RUT3: ; Instrucciones de la rutina que atiende al periférico tres.
........
RETI
ORG FF:1380H
RUT2: ; Instrucciones de la rutina que atiende al periférico dos.
........
RETI
ORG FF:1400H
RUT1: ; Instrucciones de la rutina que atiende al periférico uno.
........
RETI
ORG FF:1480H
RUT0: ; Instrucciones de la rutina que atiende al periférico cero.
........
RETI
Cuando ocurre una interrupción, la RSI se encarga de leer el puerto P1 y averiguar por chequeo
qué periférico o periféricos han interrumpido y atenderlos siguiendo un orden establecido en la
propia RSI.
Periférico 7 INT
Periférico 0 INT
+5V
Fig. 6.13 Conexión de ocho periféricos a la entrada de interrupción /INT0
.......
RET SI RUTINA DEL
SRI_6: ; Instrucciones de la rutina de atención del periférico 6 P1.3 = 0?
PERIFÉRICO 3
.......
NO
RET
SRI_5: ; Instrucciones de la rutina de atención del periférico 5
....... P1.2 = 0?
SI RUTINA DEL
RET PERIFÉRICO 2
SRI_4: ; Instrucciones de la rutina de atención del periférico 4 NO
.......
RET
SRI_3: ; Instrucciones de la rutina de atención del periférico 3 SI RUTINA DEL
P1.1 = 0?
PERIFÉRICO 1
.......
RET NO
Los flags de petición de interrupción de los Timers 0 y 1, TF0 y TF1, se activan por rebasamiento del
Timer correspondiente, excepto cuando el Timer 0 está programado en modo 3, en cuyo caso se
activan exclusivamente por rebasamiento de los registros TH0 y TL0 del Timer 0. Cuando el Timer 0
ó 1 genera una interrupción, el flag de petición de interrupción se borra automáticamente cuando la
CPU ejecuta la rutina de servicio a la interrupción.
El Timer 2 posee dos flags de interrupción, TF2 y EXF2, ubicados en el registro T2CON (tabla 6.7).
La activación de cualquiera de estos bits genera una petición de interrupción a la CPU y su borrado
debe realizarse por software. Por tanto, la rutina de servicio a la interrupción deberá determinar cuál
de los dos bits ha generado la interrupción y borrarlo.
A continuacuión se presenta el flujograma (figura 6.15) y el listado de un ejemplo de RSI del Timer 2.
Este programa incorpora las instrucciones que permiten detectar cuál de los dos flags de interrupción
del Timer 2 se ha activado, y actuar en consecuencia, de forma que si el flag activo es TF2, se ejecuta
la rutina RUTINA_TF2, y si el flag activo es EXF2, se ejecuta la rutina RUTINA_EXF2.
;****************************************************************
; RUTINA DE SERVICIO A LA INTERRUPCION TIMER 2
;**************************************************************** RSI Timer 2
ORG FF:002BH ; Dirección de comienzo de la RSI del Timer 2 como origen del
programa
JMP FF:0300H ;Salto a la dirección FF:0300H donde comienza la rutina del Timer 2 SI TF2=0
ORG FF:0300H ; Programa de inicio de la RSI del Timer 2 TF2=1?
RUTINA_TF2
JBC TF2, RUTINA_TF2 ;Si el flag activo es TF2 se pone a 0 lógico y se salta a
;la rutina que debe ejecutarse en caso de activación del flag TF2 NO
CLR EXF2 ; Si el flag TF2 no esta activo se borra el flag EXF2 y se
; ejecuta la rutina RUTINA_EXF2 EXF2=0
;Instrucciones de la rutina RUTINA_EXF2 RUTINA_EXF2
......
RETI
;Instrucciones de la rutina RUTINA_TF2 RETI
RUTINA_TF2: . . . . . . .
RETI Fig. 6.15 Flujograma de la RSI
del Timer 2
En la figura 6.16 se representa el flujograma y, a continuación, el listado de la RSI del PCA. En esta
rutina se comprueban de forma secuencial todos los flags de interrupción asociados al PCA. Si se
detecta un flag activo se borra y se ejecuta una rutina específica asociada a ese flag. Mediante el orden
de comprobación de los flags de interrupción se puede establecer el orden de prioridad de atención a
los distintos módulos que componen el PCA.
;*************************************************************
; RUTINA DE SERVICIO A LA INTERRUPCION DEL PCA RSI PCA
;*************************************************************
PCA EQU FF:0400H ;Etiqueta a la dirección de la RSI del PCA
ORG FF:0033H ;Dirección vector de interrupción del PCA SI
CF=1? RUTINA_CF
JMP PCA ;Salto a la rutina de la RSI del PCA
NO
ORG FF:0400H ;Programa de RSI del PCA
JBC CF, RUTINA_CF ;Salta si CF=1 y borra el flag.
POL_CCF0: JBC CCF0,RUTINA_CCF0 ;Salta si CCF0=1 y borra el flag SI
CCF0=1? RUTINA_CCF0
POL_CCF1: JBC CCF1,RUTINA_CCF1 ;Salta si CCF1=1 y borra el flag
NO
POL_CCF2: JBC CCF2,RUTINA_CCF2 ;Salta si CCF2=1 y borra el flag
POL_CCF3: JBC CCF3,RUTINA_CCF3 ;Salta si CCF3=1 y borra el flag
SI
POL_CCF4: JBC CCF4,RUTINA_CCF4 ;Salta si CCF4=1 y borra el flag CCF1=1? RUTINA_CCF1
; NO
;Instrucciones de la RUTINA_CF
......
SI
JMP POL_CCF0 ; Cuando termina la ejecución de RUTINA_CF CCF2=1? RUTINA_CCF2
; salto a comprobar el siguiente bit NO
; Instrucciones de la RUTINA_CCF0
....... SI
JMP POL_CCF1 ;Cuando termina la ejecución de RUTINA_CCF0 CCF3=1? RUTINA_CCF3
; salto a comprobar el siguiente bit NO
.......
; Instrucciones de la RUTINA_CCF4 SI
....... CCF4=1? RUTINA_CCF4
RETI ; Cuando termina la ejecución de RUTINA_CCF4 NO
; termina la ejecución de la RSI.
RETI
El puerto serie tiene asociado dos flags de interrupción: el flag de interrupción para recepción, RI, y el
flag de interrupción para transmisión, TI. Ambos flags están ubicados en el registro SCON (tabla 6.7).
La activación de cualquiera de estos dos flags genera una petición de interrupción a la CPU por parte
del puerto serie. Tal y como ocurre con la interrupción del Timer 2 y del PCA, el borrado de los flags
TI y RI debe realizarse por programa. Por tanto, en la RSI del puerto serie se deben incluir
instrucciones que determinen cuál de estos flags se ha activado, y lo borren.
A continuación se representa el flujograma (figura 6.17) y el listado de un ejemplo de RSI del puerto
serie. Este programa incorpora las instrucciones que permiten detectar el flag de interrupción que se ha
activado y actuar en consecuencia, de forma que si el flag activo es TI, se ejecuta la rutina RUT_TI, y
si el flag activo es RI, se ejecuta la rutina RUT_RI.
;******************************************************************
; RUTINA DE SERVICIO A LA INTERRUPCION TIMER 2
;****************************************************************** RSI puerto serie
ORG FF:0023H ; Dirección de comienzo de la RSI del puerto serie
JMP FF:0400H ; Salto a la dirección de la rutina del puerto serie
ORG FF:0400H ; Programa de inicio de la RSI del Timer 2 SI TI = 0
JBC TF2, RUT_TI ; Si el flag activo es TI se pone a 0 lógico y TI = 1? RUT_TI
; salta a la rutina correspondiente
CLR RI ; Si el flag TI no está activo se borra el flag RI y
; se ejecuta la rutina RUT_RI NO
RI = 0
;Instrucciones de la RUT_RI RUT_RI
......
RETI
;Instrucciones de la RUT_TI
RETI
RUT_TI: .......
RETI Fig. 6.17 Flujograma de la RSI del
puerto serie
Ejemplo 6.7 Control del índice de acidez (pH) del agua de un depósito
La planta que se debe controlar dispone de un sistema que neutraliza la acidez de las aguas
residuales provenientes de una planta de fabricación de papel (figura 6.18). El sistema posee un
depósito donde se mezcla el agua residual con la cantidad adecuada del componente
neutralizador, cuya función es disminuir la acidez del agua, de forma que el agua de salida del
depósito posea un pH superior a 5.5.
El sistema de control dispone además de dos actuadores V1 y V2, activos a nivel alto, cuya
función es realizar la apertura de dos válvulas. Cuando se activa el actuador V1 se abre la
válvula que permite la entrada de las aguas residuales al depósito. Cuando se activa el actuador
V2 se abre la válvula que permite el vertido de neutralizador en el depósito. Por último, existen
dos indicadores luminosos, A1 y A2, activos a nivel alto, cuya función es la de monitorizar la
apertura de las válvulas V1 y V2.
A1
Neutralizador Sistema
de control A2
V2
Entrada V1
de aguas
residuales S1
M
Medidor
pH
Descarga
8XC251
P1.2
A1
P1.3
A2
S1 INT0 P1.0 V1
M INT1 P1.1 V2
Para habilitar las cuatro fuentes de interrupción se ponen a uno lógico los bits correspondientes
del registro habilitador de interrupciones IE0: EX0, ET0, EX1 y ET1. Esto se consigue
cargando en el registro IE0 el valor 8FH (10001111b).
Por otra parte, se deben poner a uno lógico los bits IT0 e IT1 del registro TCON, con el
objetivo de que las interrupciones externas /INT0 e /INT1 se activen por nivel. Esto se
consigue almacenando en el registro TCON el valor 0AH (0000 1010b).
Por último, se debe poner el bit INTR del byte de configuración CONFIG1 a uno lógico. De
esta forma, cuando la CPU ejecute una interrupción, se cargarán en la pila, automáticamente,
los tres bytes del contador de programa, PC, y el registro de estado, PSW1.
En cuanto a la rutina de retardo, que se utiliza para temporizar el parpadeo de los indicadores
luminosos, estará compuesta de dos bucles anidados, basados en decrementar los registros R0 y
R1. Modificando el valor de los registros R0 y R1 se puede variar el tiempo de ejecución de la
rutina y, por tanto, la frecuencia de parpadeo. Para calcular el tiempo de retardo hay que
determinar el número de veces que se ejecuta cada instrucción, así como el tiempo que tarda en
ejecutarse cada una de ellas.
En la RSI del Timer 0 se debe contar el número de rebasamientos que sufre este temporizador.
Cuando el Timer 0 rebasa un número de veces equivalente a 30 s se abre la válvula V1, se
detiene el funcionamiento del Timer 0 y se habilita de nuevo la interrupción /INT0, de forma
que si el sensor S1 continúa activo se repite de nuevo la secuencia de cierre de V1.
PRINCIPAL RETARDO
INICIALIZAR: R0 = 10H
IE0 = 8FH
TCON = 0AH
IPH0 = 03H
IPL0 = 03H R1 = FFH
P1.2 = 1 DECREMENTA R1
P1.3 = 1
NO
RETARDO R1 = 0?
SI
P1.2 = 0
DECREMENTA R0
P1.3 = 0
RETARDO NO
R0 = 0?
SI
RET
INT0 T0
CERRAR VÁLVULA V1 NO
T = 30s?
SI
INICIALIZAR T0
PARAR T0
ACTIVACIÓN T0
ABRIR VÁLVULA V2
INHIBIR INT0
BORRAR IE0
RETI
HABILITAR INT0
RETI
Fig. 6.21 Flujogramas de las rutinas de servicio a las interrupciones /INT0 y Timer 0
Las rutinas de atención a las interrupciones /INT1 y Timer 1 tienen funciones similares a las
interrupciones /INT0 y Timer 0. En la figura 6.22 se presentan los flujogramas
correspondientes a ambas rutinas.
INT1 T1
ABRIR VÁLVULA V2 NO
T = 5s?
SI
INICIALIZAR T1
PARAR T1
ACTIVACIÓN T1
CERRAR VÁLVULA V2
INHIBIR INT1
BORRAR IE1
RETI
HABILITAR INT1
RETI
Fig. 6.22 Flujogramas de las rutinas de servicio a las interrupciones /INT1 y Timer1
A continuación se presentan el listado del programa principal y de la rutina de retardo.
;****************************************************************************
; VECTORIZACION INTERRUPCIONES
;****************************************************************************
ORG FF:0003H ; Vector de interrupción de /INT0
JMP RSI_INT0
ORG FF:000BH ; Vector de interrupción del Timer 0
JMP RSI_T0
ORG FF:0013H ; Vector de interrupción de /INT1
JMP RSI_INT1
ORG FF:001BH ; Vector de interrupción del Timer 1
JMP RSI_T1
;******************************************************************************
; PROGRAMA PRINCIPAL
;******************************************************************************
ORG FF:0000H
JMP PRINCIP
ORG FF:0100H
; Programación del nivel de prioridad de las interrupciones externas 0 y 1
PRINCIP: MOV IE0,#8FH ; Habilitación de las interrupciones
MOV TCON,#0AH ; Se programa /INT0 e /INT1 por nivel
MOV IPL0,#03H ; Programación de los niveles de prioridad
MOV IPH0,#03H
SETB INTR ; Cuando la CPU vectorice una interrupción cargará en la pila
; los 3 bytes del PC y el registro de estado PSW1
;Secuencia de parpadeo de los indicadores luminosos A1 y A2
SALTO0: SETB P1.2
SETB P1.3
CALL RETARDO
CLR P1.2
CLR P1.3
CALL RETARDO
JMP SALTO0
;************************************************************************
; RUTINA DE RETARDO
;*************************************************************************
ORG FF:0200H
RETARDO: MOV R0,#10H ; R0 = 10H
SALT2: MOV R1,#FFH ; R1 = FFH
SALT1: DJNZ R1,SALT1 ; Decrementa R1 y si es distinto de 0 salta a SALT1
DJNZ R0,SALT2 ; Decrementa R2 y si es distinto de 0 salta a SALT2
RET
;************************************************************************
; RUTINA DE SERVICIO A LA INTERRUPCION INT0
;*************************************************************************
ORG FF:0300H
RSI_INT0: CLR P1.0 ; Se cierra la válvula V1
SETB TMOD.0 ; Se programa el Timer 0 en modo 1
MOV TH0,#3CH ; Se inicializa el Timer 0 para temporizar 0.5 s
MOV TL0,#AFH ;
MOV R3,#00H ; El registro R3 contará los rebasamientos del Timer 0
SETB TR0 ; Puesta en marcha del Timer 0
CLR EX0 ; Se inhibe la interrupción /INT0
RETI
;**************************************************************************
; RUTINA DE SERVICIO A LA INTERRUPCION TIMER 0
;***************************************************************************
ORG FF:0400H
RSI_T0: INC R3 ; Se incrementa el contador de rebasamientos
CMP R3,59d ; Se compara el número de rebasamientos con 59
JNC SIGUE ; Si el número de rebasamientos es menor o igual que 59 continua temporizando
CLR TR0 ; En caso contrario se detiene el Timer 0 y
CLR P1.0 ; se abre la válvula V1
SETB EX0 ; Se habilita de nuevo la interrupción /INT0
CLR IE0 ; Se borra el flag de la interrupción /INT0
SIGUE: RETI ; Retorno al programa principal
;****************************************************************************
; RUTINA DE SERVICIO A LA INTERRUPCION INT1
;*****************************************************************************
ORG FF:0500H
RSI_INT1: SETB P1.1 ; Se abre la válvula V2.
SETB TMOD.4 ; Se programa el Timer 1 en modo 1
MOV TH1,#3CH ; Se inicializa el Timer 1 para temporizar 0.5 s
MOV TL1,#AFH ;
MOV R4,#00H ; El registro R4 contará los rebasamientos del Timer 1
SETB TR1 ; Puesta en marcha del Timer 1
CLR EX1 ; Se inhibe la interrupción /INT1
RETI
;**************************************************************************
; RUTINA DE SERVICIO A LA INTERRUPCION TIMER 1
;**************************************************************************
ORG FF:0600H
RSI_T1: INC R4 ; Se incrementa el contador de rebasamientos
CMP R4,09d ; Se compara el número de rebasamientos con 9
JNC SIGUE1 ; Si el número de rebasamientos es menor o igual que 9 continua temporizando.
CLR TR1 ; Se detiene el Timer 1
SETB P1.1 ; Se abre la válvula V2
SETB EX1 ; Se habilita la interrupción /INT1
CLR IE1 ; Se borra el flag de la interrupción /INT1
SIGUE1: RETI ; Retorno al programa principal
7.1 Introducción
Los microcontroladores de las familias MCS-51 y MCS-251 disponen de hasta tres contadores
internos de 16 bits, denominados Timer 0, Timer 1 y Timer 2, que pueden ser configurados de forma
individual para operar en diversos modos de trabajo. Estos contadores, en general, se incrementan en
una unidad cada vez que les entra un pulso de reloj, el cual puede provenir de la frecuencia de reloj del
microcontrolador o bien de un terminal externo, por lo que, en el primer caso, al Timer se le denomina
temporizador y, en el segundo caso, se le denomina contador.
Por otra parte hay microcontroladores que incorporan un contador adicional, cuya misión consiste en
hacer de dispositivo de watchdog (“perro guardián”). Este contador se emplea para reiniciar la CPU
cuando ésta, por problemas de interferencia electromagnética, o por algún fallo interno, pierde el
rumbo habitual de ejecución de las instrucciones, fenómeno que resulta fácil de distinguir por la
gestión caótica que hace la CPU de sus periféricos. El Timer de watchdog es un contador que se
incrementa con cada pulso del reloj de la CPU; genera entonces un reset interno que inicializa el
microcontrolador cuando llega a desbordamiento.
Con el Timer de watchdog, para que se active este reset interno, deben pasar unos pocos milisegundos,
que es el tiempo necesario para que el contador de watchdog llegue al desbordamiento. De manera
que, cuando el watchdog está activado, el programador debe insertar instrucciones de refresco o de
inicialización del Timer cada cierto intervalo de instrucciones. Se trata, pues, de que el watchdog no
llegue desbordarse, mientras el flujo de ejecución de instrucciones por parte de la CPU sea correcto. Si
la CPU pierde el control del sistema, las instrucciones se ejecutan de forma caótica, por lo que la serie
de instrucciones de refresco del watchdog no se ejecutan con la regularidad prevista, lo que causa el
desbordamiento del Timer y un auto-reset de la CPU para inicializar el sistema.
El Timer 0 y el Timer 1 pueden funcionar con cuatro modos de trabajo distintos, seleccionables
mediante el registro TMOD, Timer Mode. Los modos de trabajo son: modo 0, temporizador/contador
de 13 bits; modo 1, temporizador/contador de 16 bits; modo 2, temporizador/contador de 8 bits con
autorrecarga; y modo 3, varios contadores.
La figura 7.1 muestra el esquema funcional del Timer 0 y del Timer 1, para los modos 0 y 1 de
funcionamiento, con temporizador de 13 y 16 bits, respectivamente. En esta figura se resaltan, con un
cuadro de puntos, dos bloques: el bloque de selección de temporizador/contador y el bloque de la
lógica de control. Estos bloques son comunes al Timer 0 y al Timer 1 y a los modos de funcionamiento
0, 1 y 2 de los Timers.
INTx
Lógica de control
Fig. 7.1 Esquema funcional para los Timers 0 y 1 en los modos 0 y 1 de funcionamiento
El bloque de lógica de control utiliza una puerta de transmisión para dejar pasar, o no, los pulsos de
reloj hacia el contador (figura 7.1). En este bloque intervienen el bit TRx, Timer Run, del registro
TCON, el bit GATE del registro TMOD y el terminal de entrada /INTx, con el propósito de controlar
el paso de pulsos de reloj hacia el contador, lo que a partir de este momento se definirá como puesta
en marcha o parada del contador. Con los bits TRx y GATE se puede poner en marcha o parar el
Timer de forma directa, por software, o bien, por medio del estado lógico del terminal /INTx, por
hardware.
Observando el circuito de la lógica de control, se deduce que si el bit GATE se pone a 0 lógico, en la
entrada de la puerta OR (figura 7.1), habrá un 1 lógico y, por tanto, un 0 lógico en la entrada de la
puerta AND; en esta situación queda claro que la puerta está gobernada por el estado lógico del bit
TRx. Entonces, si TRx vale 0 lógico, la puerta queda abierta y el Timer parado, y si TRx vale 1 lógico,
la puerta queda cerrada y el Timer en marcha, y se incrementa a cada pulso de entrada. En esta
situación, con el bit GATE a 0 lógico, la puesta en marcha o la parada del Timer depende del estado
del bit TRx, y queda, en consecuencia, gobernado por software.
Si GATE se pone a 1 lógico, a la entrada de la puerta OR, tras la puerta inversora (figura 7.1), habrá
un 0 lógico; luego, el estado lógico de la puerta OR dependerá directamente del estado lógico del
terminal /INTx. Si al mismo tiempo, el bit TRx se pone a 1 lógico, queda claro que el gobierno de la
puerta de transmisión dependerá del terminal /INTx, que pondrá en marcha el Timer cuando /INTx
esté a 1 lógico, y parará el Timer cuando /INTx esté a 0 lógico, lo que se mencionará, a partir de
ahora, como puesta en marcha o parada del contador por hardware, es decir, por el estado lógico de
/INTx.
La determinación del modo de funcionamiento del Timer 0 y del Timer 1 se realiza con los bits M0 y
M1 del registro TMOD: existen, en efecto, en este registro un par de bits para cada Timer (tabla 7.1).
El contenido del registro TCON se muestra en la tabla 6.2.
Timer 1 Timer 0
Bit Comentario
GATE GATE a 0 lógico hace que el Timer se gobierne mediante TRx, con TRx a 1
lógico se pone en macha el Timerx y con TRx a 0 lógico se detiene (x=0 ó 1).
GATE a 1 lógico, junto con TRx a 1, hace que el Timer se gobierne por
hardware, mediante el estado lógico de la entrada /INTx.
C/T Selecciona entre pulsos de la señal de reloj o pulsos del terminal Tx. Si C/T está a
0 se toman los pulsos de la señal de reloj y si C/T está a 1 se toman de Tx.
M1 M0 Selección del modo de trabajo
0 0 Modo 0. Temporizador/contador de 13 bits.
0 1 Modo 1. Temporizador/contador de 16 bits.
1 0 Modo 2. Temporizador/contador de 8 bits con autorrecarga.
1 1 Modo 3. Varios contadores.
El sentido del contador es siempre ascendente y se incrementa con cada pulso de entrada. El
rebasamiento del Timer se produce cuando pasa de tener todos los bits de uno lógico a cero lógico;
entonces se activa el bit correspondiente de rebasamiento, TFx, y se genera una interrupción a la CPU.
XTAL1 ÷12
Interrupción
0
TLx TFx
Tx 1
C/T
TRx
THx
GATE x=0ó1
INTx
Fig. 7.2 Esquema funcional para los Timers 0 y 1 en el modo 2 de funcionamiento
;***************************************************************
; Generación de una señal periódica
; Rutina de Vectorización
;***************************************************************
ORG 0H
LJMP Inicio
ORG 0BH MCS-51
LJMP RSI_Timer0
;***************************************************************
; Rutina de Inicio
;*************************************************************** P1.0
Inicio: SETB PT0 ;Asigna prioridad alta al Timer 0
SETB ET0 ;Habilita interrupción del Timer 0
SETB EA ;Habilita bit de interrupción general
MOV TMOD,#02H ;M1=1 y M0=0 (Modo 2), Fig. 7.3 Generación de señal en el
; GATE=0 y C/T=0 del Timer 0 ejemplo 7.1
MOV TL0, #156 ;Pone valor 156 en TL0 (256-100)
MOV TH0, #156 ;Pone valor de recarga en TH0 (256-100)
SETB TR0 ;Pone marcha el contador
;***************************************************************
; Rutina de Principal
;***************************************************************
Principal: SJMP Principal ;Bucle infinito sin una tarea concreta
;***************************************************************
; Rutina de servicio del Timer0
;***************************************************************
RSI_Timer0:CPL P1.0 ;Complementa P1.0. Pasa de 1 a 0, y de 0 a 1
RETI ;Fin de rutina. El bit TF0 se borra automáticamente
El Timer 0 está gestionado completamente por interrupciones, de manera que cada vez que
llega a desbordamiento se activa el bit TF0, TF0=1, se produce una interrupción a la CPU y se
recarga el valor del registro TH0 en el registro TL0. En la rutina de atención a la interrupción
del Timer 0, RSI_Timer0, basta con complementar el estado lógico de la patilla P1.0, para
generar la frecuencia requerida. Con esta instrucción el microcontrolador lee el estado de la
patilla, lo complementa (pasa de 0 lógico a 1 lógico, y viceversa) y escribe el nuevo estado en
la patilla.
Para determinar el valor de recarga del registro TH0, se debe considerar que el período
necesario para generar frecuencia de 5 kHz es de 200 µs, por lo que la patilla P1.0 se debe
complementar cada 100 µs, es decir, la mitad del período. Además, desde que se produce la
interrupción (estado S5P2 del ciclo máquina), hasta que se vectoriza la interrupción del Timer
0, transcurren tres ciclos máquina en el mejor de los casos, y la instrucción CPL P1.0 se ejecuta
en un ciclo máquina. Por tanto, el estado lógico de la patilla P1.0 cambiará, al menos, cuatro
ciclos máquina después de que se halla activado el bit TF0.
El valor de recarga de TH0 debe ser de 156, es decir, el valor de la diferencia entre 256 (valor
de rebasamiento) y el tiempo deseado, 100 µs. Se debe tener en cuenta que para un reloj de
12MHz, el Timer 0 se incrementa cada microsegundo y que un ciclo máquina tiene la duración
de 1 µs.
T1 P1.0 T5
P1.4
T2 T6
P1.1 P1.5
T3
P1.2
T4 P1.3
80C31
P1.6 f1
/INT0 P1.7 f2
En este ejemplo el microcontrolador debe generar en la patilla P1.6 una frecuencia de 4kHz,
5kHz, 10kHz y 20kHz, si se pulsan las teclas T1, T2, T3 o T4, respectivamente. Las teclas T5 y
T6 afectarán a la frecuencia de la patilla P1.7. Al pulsar T5 se generará en P1.7 una frecuencia
de 25kHz; al pulsar T6 la frecuencia será de 50kHz. Inicialmente, por defecto, en P1.6 y en
P1.7 se generará una frecuencia de 2kHz. Cuando se pulse una tecla se generará la frecuencia
correspondiente, y cuando no se pulse ninguna se volverá a generar la frecuencia inicial de
2kHz.
;********************************************************************
; Generación de una señal periódica
;********************************************************************
ORG 0H ; Vectorización de interrupciones
LJMP Inicio
ORG 03H
LJMP RSI_Int0
ORG 0BH
LJMP RSI_Timer0
ORG 01BH
LJMP RSI_Timer1
;********************************************************************
; Rutina de Inicio
;********************************************************************
Inicio: SETB IT0 ;Interrupción /INT0 activa por flanco descendente
SETB PT0 ;Asigna prioridad alta al Timer 0
En la rutina de inicio se ha activado la interrupción /INT0 por flanco descendente, por lo que la
interrupción sólo se producirá una vez, cuando se pulse una tecla, al detectar la CPU un flanco de
bajada. En la rutina de inicio se le asigna prioridad alta al Timer 0 y al Timer 1, por ser el núcleo de
este ejemplo. El Timer 0 y el Timer 1 se configuran en el modo 2 de autorrecarga contando pulsos del
reloj.
Para determinar el valor de los registros TH0 y TH1, de acuerdo con la frecuencia especificada, se
debe tener en cuenta que la frecuencia se genera a través de la instrucción CPL en la rutina de RSI de
cada Timer. La instrucción CPL complementa el valor del terminal del puerto cada vez que un
temporizador llega a rebasamiento, por lo que para generar una frecuencia se debe emplear la mitad
del período de ésta. Con una frecuencia de reloj de 12 MHz, el período de cada pulso de reloj es de 1
µs, los temporizadores, pues, se incrementan cada microsegundo. Luego, para generar una frecuencia
determinada en el Timer 0 ó 1, el valor del registro TH0 o TH1 debe ser:
Período reloj
TH 0,1 = Valor de rebasamiento -
2
En este ejemplo, para generar una frecuencia de 2 kHz el valor de TH0 es de 236, para 4 kHz el valor
es de 131, etc. El Timer 0 llega a rebasamiento cuando TL0 pasa de FFH a 00H, por lo que el valor de
rebasamiento, es decir, el valor máximo del Timer, es de 256 o FFH+1.
En el modo 3 el contador formado por TL0 utiliza todos los bits de control propios del Timer 0, para
llevar a cabo el mismo tipo de funcionamiento que el descrito para los otros modos; o sea, usa los bits
C/T, GATE, TR0 y /INT0. No obstante, para el contador formado por el registro TH0 sólo se dispone
del bit de control TR1, por lo que este contador tiene su funcionamiento restringido: sólo puede
ponerse en marcha y pararse mediante el bit TR1. El contador TH0, además, sólo puede contar pulsos
procedentes del reloj del microcontrolador.
A nivel de desbordamiento, el contador formado por TL0 afecta al bit TF0, mientras que el contador
formado por TH0 afecta al bit TF1, que en los otros modos pertenece al Timer 1.
En cuanto al Timer 1, para el modo 3, es obvio que no puede utilizar los bits TR1 y TF1 en su
funcionamiento usual, lo que significa que, cuando el Timer 1 se desborde, no se activará el bit TF1, y
que tampoco se podrá usar el bit TR1 para activar o para parar el Timer. La forma de arrancar y parar
el Timer 1 consiste en entrar y salir de su propio modo 3; es decir, entrando en el modo 3 se pone en
marcha el Timer 1, y saliendo del modo 3 se detiene el Timer 1. De todos modos, el Timer 1 puede ser
utilizado por el puerto serie como base para la generación de la velocidad de transmisión en baudios o
en cualquier otra aplicación en donde no se necesite producir una interrupción.
0 Interrupción
TL0 TF0
T0 1
C/T
TR0
GATE
Interrupción
INT0 1/12 Fosc TH0 TF1
TR1
Fig. 7.5 Esquema funcional en el modo 2 de funcionamiento
7.2.2 Timer 2
El Timer 2 es un contador de 16 bits que está formado a partir de los registros TL2 y TH2, de 8 bits
cada uno, conectados en cascada. Este Timer está presente en todas las versiones de la MCS-51 con
tres temporizadores internos, y puede trabajar hasta con cuatro modos distintos de funcionamiento:
modo autorrecarga, modo captura, modo Baud Rate y modo Clock-out. La forma de trabajar con el
Timer 2 se determina a partir de los registros T2MOD y T2CON, (tablas 7.2 y 7.3, respectivamente).
Estos registros permiten determinar el modo de funcionamiento del Timer 2, controlar su puesta en
marcha, programar su modo de operación (contador o temporizador) y detectar el desbordamiento.
En la tabla 7.4 se indican los cuatro modos de operación en los que puede funcionar el Timer 2,
dependiendo del estado de los bits RCLK, TCLK, CP/RL2 y T2OE.
Bit Comentario
-- Bit reservado.
T2OE Bit de habilitación del Timer 2.
En el modo Clock-out, T2OE conecta la salida de desbordamiento con el terminal T2.
DCEN Bit de sentido de cuenta.
DECEN=0 hace que el sentido de la cuenta sea ascendente. DCEN=1 hace que el
sentido pueda ser ascendente o descendente.
Bit Comentario
TF2 Bit de desbordamiento. TF2=1 al producirse un desbordamiento. Este bit no se
activa si RCLK=1 o TCLK=1. Debe borrarse por software.
EXF2 Bit de entrada externa. EXF2 se pone a 1 lógico al producirse un flanco
descendente en el terminal T2EX, siempre y cuando EXEN2 esté habilitado.
RCLK Bit de reloj en recepción. RCLK se pone a 1 lógico cuando se produce un
desbordamiento en el Timer 0.
TCLK Bit de reloj en transmisión
EXEN2 Bit de habilitación de entrada externa. En general, si EXEN2=1 permite la
activación de EXF2 con un flanco de descendente en T2EX. También realiza
funciones específicas en todos los modos de funcionamiento del Timer.
TR2 Bit de puesta en marcha y parada. TR2=1 pone en marcha el Timer 2. TR2=0
detiene el Timer 2.
C/T2 Bit de selección de temporizador/contador. Con C/T2=0 el Timer cuenta pulsos
de reloj (÷12). Con C/T2=1 el Timer cuenta pulsos de la entrada T2.
CP/RL2 Bit de captura/recarga. Con CP/RL2=1 se produce una captura al aplicar un
flanco negativo en T2EX, si EXEN2=1. Con CP/RL2=0 se produce una recarga al
aplicar un flanco negativo en T2EX, si EXEN2=1.
Si RCLK=1 o TCLK=1 se ignora CP/RL2 y se fuerza la recarga del Timer 2 al
producirse un desbordamiento en su valor.
En este modo, si el bit EXEN2 del registro T2CON se pone a 1 lógico y se produce un flanco de
bajada en el terminal T2EX del microcontrolador, el valor actual de los registros TH2 y TL2 se copia
en los registros RCAP2H y RCAP2L del área de SFR, hecho al que se le denomina captura. Al mismo
tiempo, el flanco de bajada producido hace que el bit EXF2 del registro T2CON se ponga a 1 lógico y
se genera una interrupción automática. Así pues, en este modo las fuentes de interrupción hacia la
CPU pueden ser por medio del bit de rebasamiento TF2, o bien por medio del bit EXF2. En este
último caso, se puede considerar al terminal T2EX como una nueva fuente de interrupción externa, al
igual que /INT0 y /INT1. En el caso de que produzca una interrupción, la rutina de RSI que se ejecuta
es la misma, tanto para el bit TF2, como para el bit EXF2, de forma que la rutina de RSI debe
comprobar cuál de las dos posibles interrupciones se ha activado.
La puesta en marcha y la parada del Timer 2 se realiza con el bit TR2 del registro T2CON. Con TR2 a
1 lógico se pone en marcha el Timer, que queda habilitado para contar pulsos; con TR2 a 0 lógico se
detiene el Timer.
XTAL1 ÷12
0
TL2 TH2 TF2
T2 1
C/T2 TR2
Interrupción
RCAP2H RCAP2L
T2EX EXF2
EXEN2
El bit DCEN, tras un reset del microcontrolador, se pone a 0 lógico, así que, por defecto el Timer 2 en
el modo autorrecarga funciona como un contador ascendente de 16 bits.
XTAL1 ÷12
0
TH2 TL2 TF2
1
T2
TR2
C/T2
RCAP2H RCAP2L
Interrupción
T2EX EXF2
EXEN2
Cuando T2EX está a 1 lógico, el Timer 2 cuenta de forma ascendente, en cuyo caso, el Timer puede
llegar a desbordamiento; se activa entonces el bit TF2, se produce una recarga del valor de los
registros RCAP2H y RCAP2L hacia TH2 y TL2, respectivamente, y se genera una interrupción
automática siempre y cuando se haya habilitado de forma previa.
Cuando T2EX está a 0 lógico, el Timer 2 cuenta en sentido descendente, es decir, se decrementa su
valor con cada pulso de entrada. En este sentido de la cuenta, el Timer 2 también puede llegar a un
rebasamiento, que se produce cuando el contenido de los registros TH2 y TL2 llega a ser igual al valor
almacenado en los registros RCAP2H y RCAP2L, respectivamente. En este caso, se activa el bit TF2,
y se produce una petición de interrupción y una recarga del valor FFH en cada uno de los registros,
TH2 y TL2.
Al mismo tiempo, cuando se produce cualquiera de los dos tipos de desbordamiento mencionados, el
bit EXF2 complementa su valor; es decir, si EXF2 está a 1 lógico, cambia su valor a 0 lógico, y
viceversa. El bit EXF2 no genera petición de interrupción al microcontrolador, y se puede utilizar
como el bit 17 del contador, es decir, se contempla el contador como un Timer de 17 bits (donde
EXF2 es el bit 17).
EXF2
XTAL1 ÷12
0 Interrupción
TH2 TL2 TF2
1
T2
TR2
C/T2
Sentido de la cuenta
1 = ascendente
T2EX 0 = descendente
RCAP2H RCAP2L
7.2.2.3 Modo generador de baudios para el puerto serie (Baud Rate Generator Mode)
En este modo, el Timer 2 queda configurado como generador de baudios para fijar la velocidad de
transmisión del puerto de comunicación serie del microcontrolador. Este modo se selecciona al activar
los bits RCLK y/o TCLK de registro T2CON (tabla 7.4).
En este modo el desbordamiento del Timer no genera petición de interrupción, como ocurre con los
otros modos. La interrupción, sin embargo, sí que se genera al detectar un flanco de bajada en la
entrada T2EX, siempre y cuando el bit EXEN2 esté activado (figura 7.9).
La frecuencia de la señal de reloj generada se establece modificando el valor de los registros RCAP2H
y RCAP2L, según la siguiente ecuación:
FOSC
Frec _ reloj =
4⋅(65535−RCAP 2H,RCAP 2L )
El rango de frecuencias que se puede generar está comprendido entre los 61Hz y los 4MHz, para una
frecuencia de reloj de 16MHz.
A modo de resumen, para que el Timer 2 trabaje en modo Clock-out, el bit T2OE del registro T2MOD
se debe poner a 1 lógico, el bit C/T2 del registro T2CON se debe poner a 0 lógico, y el bit TR2 debe
estar a 1 lógico.
El Timer 2 se puede usar como generador de baudios para el puerto serie y, también de forma
simultánea, como generador de reloj, aunque las frecuencias generadas no se pueden determinar de
forma independiente, pues comparten los mismos registros de recarga.
XTAL1 ÷12
0
TH2 TL2
1
TR2
C/T2
T2
RCAP2H RCAP2L
÷2
T2OE
T2EX EXF2
Interrupción
EXEN2
Fig. 7.9 Modo Clock-out para el Timer 2
Los Timers 0, 1 y 2 pueden contar pulsos procedentes de los terminales T0, T1 y T2, respectivamente.
Para ello los bits C / T del registro TMOD, en el caso de los Timers 0 y 1, y el bit C / T 2 para el
Timer 2, deben estar a 1 lógico. Los registros de los Timers se incrementan cada vez que se detecta, en
los terminales T0, T1 y T2, una transición de 1 a 0 lógico.
El estado lógico de cada uno de estos terminales de entrada se comprueba en la fase 2 del estado 5,
S5P2, de cada ciclo máquina. El valor de los registros de los Timers se incrementa cuando en un ciclo
máquina se detecta un 1 lógico y un 0 lógico en el siguiente ciclo. El nuevo valor de los registros se
muestra en el estado S3P1 del ciclo máquina siguiente al que se ha detectado la transición.
La máxima frecuencia del terminal de entrada es fclok/24, puesto que se tarda dos ciclos máquina en
reconocer una transición de 1 a 0 lógico. Para una frecuencia de reloj de 12MHz la máxima frecuencia
de terminal T0, T1 o T2 es de 500kHz.
P0.2 A2
R
P2.7 P0.3 A3 R
dp /EL dp
Ánodo común dp
Vcc
Sensor P0.4 Tr1 Tr2 Tr3 Tr4
Cuenta
P0.5
P1.2
P0.6
P0.7
Vcc Sensor
Descuenta
Fig. 7.10 Circuito del contador de piezas con teclado matricial del ejemplo 7.3
Los cuatro dígitos de la figura 7.10 se deben encender de manera secuenciada para que el
número se distinga correctamente, tal y como se explicaba en el apartado 5.10.6. Al mismo
tiempo, la lectura del teclado matricial también precisa de una secuencia de escrutinio, en la
cual se comprueba, columna a columna, si se han pulsado las teclas asociadas. En
consecuencia, en el circuito de la figura 7.10, se desea utilizar la secuencia de refresco de los
cuatro dígitos de siete segmentos, para efectuar, a la vez, la secuencia de escrutinio de las
columnas del teclado matricial. Esta secuencia se llevará a cabo automáticamente mediante las
interrupciones del Timer 2.
Las filas del teclado matricial pueden activar la entrada de interrupción /INT1 mediante la
puerta AND de la figura 7.10. La secuencia situará un 0 lógico en la patilla P0.7, mientras las
patillas P0.4, P0.5 y P0.6 permanecen a 1 lógico, pondrá el transistor Tr4 en saturación y
encenderá el dígito correspondiente a las unidades. Si en este momento se pulsan las teclas F1 o
F2, se provocará una interrupción en /INT1. Transcurrido un tiempo determinado, el 0 lógico
se sitúa en el terminal P0.5, mientras los otros terminales están a 1 lógico; se pone, así, el
transistor Tr3 en saturación y se enciende el dígito de las decenas. De esta manera se procede
hasta que se pone un 0 lógico en la patilla P0.7 y se enciende el dígito correspondiente a los
millares. En este caso, la secuencia se repetirá con una frecuencia de 1 kHz, que establecerán
las interrupciones del Timer 2.
Cada vez que llega un pulso de “cuenta” se debe incrementar el valor del contador, y cuando se
activa el sensor de “descuenta” se debe decrementar el contador. Si el valor del contador
sobrepasa el valor 9999, éste no se incrementará, y si llega un pulso de “descuenta” cuando el
valor es de 0000, el contador no se decrementará. La tecla “reset” activa la interrupción /INT0
y pone a cero el valor del contador.
Cuando se detecte que una tecla ha sido pulsada se mostrará un carácter determinado que
indique, en el dígito conectado al puerto P2, la tecla pulsada. Para la tecla “Up” se mostrará el
carácter “U”, para la tecla “Rigth” se mostrará el carácter “r”, para “Enter” el carácter “E”, para
“F1” el carácter “1.”, para “Down” el carácter “d”, para “Left” el carácter “L”, para “Clear” el
carácter “C” y para “F2” el carácter “2.”. El dígito conectado al puerto P2 mostrará siempre el
carácter correspondiente a la última tecla pulsada.
;**********************************************************************
; Refresco de 4 dígito de siete segmentos y de teclado matricial
;**********************************************************************
ORG 0H ; Vectorización de interrupciones
LJMP Inicio
ORG 03H
LJMP RSI_Int0
ORG 013H
LJMP RSI_Int1
ORG 02BH
LJMP RSI_Timer2
;**********************************************************************
; Rutina de Inicio
;**********************************************************************
Inicio: MOV P2, #0 ;Apaga el dígito conectado a P2
SETB IT0 ;Interrupción /INT0 activa por flanco descendente
SETB IT1 ;Interrupción /INT1 activa por flanco descendente
SETB PX1 ;Asigna prioridad alta a /INT1
SETB EX0 ;Habilita interrupción de /INT0
SETB EX1 ;Habilita interrupción de /INT1
SETB ET2 ;Habilita interrupción del Timer 2
MOV T2CON, #0 ;Timer 2 funcionando en 16 bits con autorrecarga
MOV T2MOD, #0 ;Timer 2 (DCEN=0)
MOV RCAP2L, #05H ;Carga recarga para interrumpir cada 250 µs
MOV RCAP2H, #0FFH ; en RCAP2L y RCAP2H
MOV TL2, #05H
MOV TH2, #0FFH
SETB EA ;Habilita bit de interrupción general
SETB TR2 ;Pone en marcha el Timer 2
;**********************************************************************
; Rutina Principal
;**********************************************************************
Principal: JNB P1.2, Conta ;Comprueba si se ha pulsado “Cuenta”
JNB P1.3, Decre ;Comprueba si se ha pulsado “Descuenta”
MOV P2, B ;Carga B en P2, para mostrar en dígito
SJMP Principal ;Bucle infinito
;**********************************************************************
; Rutina de servicio de /INT0
;**********************************************************************
RSI_Int0: MOV R0, #0 ;Borra unidades
MOV R1, #0 ;Borra decenas
MOV R2, #0 ;Borra centena.
MOV R3, #0 ;Borra millares
MOV P2, #0 ;Apaga dígito conectado a P2
MOV B, #0 ;Borra registro B
RETI
;**********************************************************************
; Rutina de servicio de /INT1
;**********************************************************************
RSI_Int1: JNB P1.0, Fila_0 ;¿Ha pulsado una tecla de la fila 0?
SJMP Fila_1 ;Si no, debe ser la fila 1
;**********************************************************************
;Rutina Conta
;**********************************************************************
Conta: CJNE R0, #9, Unidad ;Compara unidad
CJNE R1, #9, Decena ;Compara decena
CJNE R2, #9, Centena ;Compara centena
CJNE R3, #9, Millar ;Compara millar
SJMP Principal
Unidad: INC R0 ;Incrementa unidades
SJMP Principal
Decena: MOV R0, #0 ;Pone a 0 las unidades
INC R1 ;Incrementa decenas
SJMP Principal
Centena: MOV R0, #0 ;Pone a 0 unidades y decenas
MOV R1, #0
INC R2 ;Incrementa centenas
SJMP Principal
Millar: MOV R0, #0 ;Pone a 0 unidades, decenas y centenas
MOV R1, #0
MOV R2, #0
INC R3 ;Incrementa millares
SJMP Principal
;**********************************************************************
;Rutina Decre
;**********************************************************************
Decre: CJNE R0, #0, D_uni ;Compara unidad
CJNE R1, #0, D_dece ;Compara decena
CJNE R2, #0, D_cent ;Compara centena
CJNE R3, #0, D_mill ;Compara millar
LJMP Principal
D_uni: DEC R0 ;Decrementa unidad
LJMP Principal
D_dece: MOV R0, #9 ;Pone a 9 unidad
DEC R1 ;Decrementa decena
LJMP Principal
D_cent: MOV R0, #9 ;Pone a 9 unidad
MOV R1, #9 ;Pone a 9 decena
DEC R2 ;Decrementa centena
LJMP Principal
D_mill: MOV R0, #9 ;Pone a 9 unidad
MOV R1, #9 ;Pone a 9 decena
MOV R2, #9 ;Pone a 9 centena
DEC R3 ;Decrementa millar
LJMP Principal
En la rutina de “Inicio” el puerto P2 se pone a cero, debido a que inicialmente está a FFH (o
sea, todos sus terminales a 1 lógico); por tanto, debe ponerse a cero para que ninguno de los
leds del dígito esté encendido. En la rutina, las entradas /INT0 y /INT1 se configuran activas
por flanco descendente y se habilitan las interrupciones de /INT0, de /INT1 y del Timer 2. El
Timer 2 se configura para que funcione como un temporizador de 16 bits con autorrecarga;
para ello se colocan los bits RCLK, TCLK y CP/RL2, del registro T2CON, a 0 lógico. El Timer
cuenta pulsos internos del reloj del microcontrolador, por lo que el bit C/T2 del registro
T2CON se pone a 0 lógico. En el Timer 2 es necesario inhibir las interrupciones procedentes
del terminal T2EX (figura 7.7); por tanto, el bit EXEN2 también se pone a 0 lógico. Por último,
para que el temporizador funcione sólo en sentido ascendente, el bit DCEN del registro
T2MOD se pone a 0 lógico.
Para que la secuencia de refresco de los dígitos sea de 1kHz, el valor de recarga del Timer ha
de ser de FF05H, pues el período de la secuencia es de 1ms y, al haber cuatro dígitos, el tiempo
que debe permanecer encendido cada dígito es de 0.250 ms. FF05H es el resultado de restar
250 (o FAH) de 64k (o FFFFH).
El puerto P0 inicialmente también tiene todos sus terminales en estado 1 lógico, lo que no
supone ningún inconveniente, pues las puertas inversoras conectadas a los transistores Tr1, Tr2,
Tr3 y Tr4, aseguran que los transistores estén en corte y los dígitos permanezcan apagados.
La rutina de RSI del Timer 2 utiliza el registro R5 como contador en base 3, y determina el
dígito que se va a encender, según sea el valor de R5. Si vale cero se enciende el dígito
correspondiente a las unidades, si vale 1 se enciende el dígito de las decenas, si vale 2 se
enciende el dígito de las centenas y si vale 3 se enciende el dígito de los millares. El valor de
R5 se actualiza con la instrucción INC, de forma que cada vez que la rutina de RSI se ejecuta,
el registro se incrementa en una unidad, excepto cuando vale 3, que se pone a cero. El
contenido de los registros R0, R1, R2 o R3 se carga en el acumulador y se fuerzan sus cuatro
bits altos a 1 lógico mediante una instrucción ORL, de manera que todos los dígitos estén
apagados y se encienda el dígito que corresponda con la instrucción CLR.
La rutina principal está formada por un bucle infinito en el cual se comprueba el estado de los
sensores “cuenta” y “descuenta”, y donde se pone, en el dígito conectado a P2, el carácter de la
tecla pulsada en el teclado matricial.
Cuando operan como temporizadores, cada Timer se incrementa una vez cada cierto intervalo de
tiempo; cuando funcionan como contadores se incrementan cada vez que ocurre una transición
negativa en un pin concreto del microcontrolador.
Por otra parte, el microcontrolador incorpora un temporizador watchdog que permite generar un reset
por software, si se produce alguna anomalía en la ejecución del programa.
Cada Timer está compuesto por dos registros de 8 bits ubicados en el área de registros de función
específica, SFR. En concreto, el Timer 0 está formado por los registros TH0 y TL0, el Timer 1 por los
registros TH1 y TL1 y el Timer 2 por los registros TH2 y TL2 (tabla 7.1).
También se dispone de cuatro registros ubicados en el área SFR que permiten controlar y programar
adecuadamente las prestaciones de funcionamiento de los Timers. Los registros de programación
asociados al Timer 0 y al Timer 1 son: TMOD, registro de control de modo del temporizador/contador,
y TCON, registro de control del temporizador/contador.
Los registros de programación para el Timer 2 son: T2MOD, registro de control de modo del Timer 2,
y T2CON, registro de control del Timer 2.
Tabla 7.5 Registros asociados a los Timers 0, 1 y 2 y al timer watchdog de la familia MCS-251
En la figura 7.11 está representado el esquema funcional básico de los Timers 0, 1 y 2. La parte central
del Timer está constituida por dos registros de 8 bits: THx y TLx (x = 0, 1 y 2), conectados en cascada
para formar un temporizador de 16 bits.
XTAL1 ÷12
Petición de
Desbordamiento
0 interrupción
THx TLx
TFx
(8 bits) (8 bits)
1
Tx
C/Tx
x = 0, 1 ó 2
TRx
Fig. 7.11 Estructura básica de los Timers 0, 1 y 2
Los Timers pueden ser programados para que trabajen como temporizador o como contador, mediante
el bit C/Tx, con x = 0, 1 ó 2, dependiendo del Timer de que se trate. En la tabla 7.6 se indica la
ubicación de cada uno de estos bits.
Tabla 7.6 Ubicación de los bits C/Tx
Bit Ubicación
C/T0 TMOD.2
C/T1 TMOD.6
C/T2 T2CON.1
En este caso el Timer se incrementa en una unidad cada microsegundo, luego, para temporizar
1ms, el Timer 0 se deberá incrementar 1.000 veces. De esta forma, controlando el número de
incrementos que sufre el Timer se obtiene la rutina de retardo deseada.
;****************************************************************************
; RUTINA DE RETARDO
;****************************************************************************
ORG FF:0000H ;
...
CALL RETARDO ;
ORG FF:0100H ; La rutina de retardo empieza en la dirección FF:1000H
RETARDO: MOV R0,TH0 ; Se carga el valor del Timer en el registro WR0
MOV R1,TL0 ;
MOV WR2,#1000D ; Se carga en el registro WR2 el valor 1.000 decimal
CMP WR2,WR0 ; Se compara el contenido del Timer 0 con 1.000
JG RETARDO ; Si el contenido del Timer 0 es menor o igual a 1.000
; continuamos en la rutina de retardo
RET ; En el momento que el contenido del Timer 0 sea mayor a 1.000 se termina la rutina de retardo
1
La CPU comprueba el estado de las entradas externas de los Timers en cada ciclo de periférico , en
concreto en el segundo período del estado 5. Cuando la CPU detecta un 1 lógico en un ciclo y un cero
lógico en el siguiente ciclo, el Timer correspondiente se incrementa en una unidad (figura 7.12). El
1
Un ciclo de periférico equivale a 12 períodos de reloj agrupados en 6 estados, cada uno de ellos compuesto por dos
períodos.
valor del Timer se actualiza en el primer período del estado 3 del ciclo de periférico que viene después
de detectar el flanco de bajada.
S5P5 S5P5
1
T2, T1, T0
0
Fig. 7.12 Proceso de incremento de un Timer programado como contador
Teniendo en cuenta que un ciclo de periférico tiene una duración de 12 períodos de reloj, se necesitan,
como mínimo, 24 períodos de reloj para reconocer un flanco de bajada, por lo que la máxima
velocidad de cuenta es de fclock/24.
Para controlar el funcionamiento de los Timers 0 y 1 se utilizan los registros TMOD y TCON (tablas
7.8 y 7.9). Los cuatro bits de menor peso del registro TMOD están asociados al Timer 0 y los cuatro
bits de mayor peso controlan el funcionamiento del Timer 1. Por otra parte, los bits 4 y 5 del registro
TCON están relacionados con el Timer 0, y los bits 6 y 7 con el Timer 1. Estos bits permiten
programar el modo de funcionamiento de los Timers, controlar su puesta en marcha, programar su
modo de operación, como contador o como temporizador, y detectar su desbordamiento.
• Control por software: programando el valor lógico del bit GATEx (con x = 0 ó 1).
• Control por hardware: aplicando un nivel de tensión adecuando al pin /INTx (con x = 0 ó 1).
Número Nombre
Función
de bit del bit
7 GATE1 Bit GATE del Timer 1. Con GATE1 = 0, el Timer 1 se pone en marcha si TR1=1. Si
GATE1 = 1 y TR1 = 1, el Timer 1 se pone en marcha colocando un 1 lógico en el pin
/INT1 (P3.3).
6 C/T1 Selección de temporizador/contador del Timer 1. C/T1 = 0: el Timer 1 funciona como
temporizador. C/T1 = 1: el Timer 1 funciona como contador.
5, 4 M11, M01 Selector de modo del Timer 0.
M11 M01
0 0 Modo 0: El Timer 0 funciona como un Timer de 13 bits.
0 1 Modo 1: El Timer 0 funciona como un Timer de 16 bits.
1 0 Modo 2: El Timer 0 funciona como un Timer de 8 bits (TL0) y se
recarga con el valor que hay en TH0 cuando sufre desbordamiento.
1 1 Modo 3: El Timer se para.
3 GATE0 Bit GATE del Timer 0
Cuando GATE0 = 0, el Timer 1 se pone en marcha con TR0=1. Si GATE0 = 1 y TR0
= 1, el Timer 0 se pone en marcha colocando un 1 lógico en el pin /INT0 (P3.2).
2 C/T0 Selección de temporizador/contador del Timer 0. C/T0 = 0: el Timer 0 funciona como
temporizador. C/T0 = 0: el Timer 0 funciona como contador.
1, 0 M10, M00 Selector de modo del Timer 0.
M10 M00
0 0 Modo 0: El Timer 0 funciona como un Timer de 13 bits.
0 1 Modo 1: El Timer 0 funciona como un Timer de 16 bits.
1 0 Modo 2: El Timer 0 funciona como un Timer de 8 bits (TL0) y se
recarga con el valor que hay en TH0 cuando sufre desbordamiento.
1 1 Modo 3: El Timer 0 funciona como dos Timers de 8 bits: TL0 y TH0.
Número Nombre
Función
de bit del bit
7 TF1 Flag de desbordamiento del Timer 1.
Se pone a 1 cuando el Timer 1 sufre desbordamiento, o sea cuando pasa de la
combinación todo unos a la combinación todo ceros.
6 TR1 Flag de puesta en marcha del Timer 1. Cuando está a 1 lógico el Timer 1 está habilitado
para funcionar, en caso contrario esta parado.
5 TF0 Flag de desbordamiento del Timer 0. Se pone a 1 cuando el Timer 0 sufre
desbordamiento, o sea cuando pasa de la combinación todo unos a la combinación todo
ceros.
4 TR0 Flag de puesta en marcha del Timer 0. Cuando está a 1 lógico el Timer 0 está habilitado
para funcionar; en caso contrario esta parado.
Este tiempo se puede medir utilizando uno de los Timers del microcontrolador, por ejemplo el
Timer 0. Para realizar esta medida se monta el dispositivo mostrado en la figura 7.13 que
incorpora un sensor de corriente, un sensor de tensión y una puerta AND cuya salida se ha
conectado al pin P3.2, /INT0, para poder controlar mediante hardware el Timer 0. El sensor de
corriente se activa cuando la corriente es mayor o igual a 400A. Por otra parte, el sensor de
tensión se activa para una tensión mayor o igual a 12V. El nivel activo de ambos sensores es 1
lógico, de forma que, cuando los dos están activos, la salida de la puerta AND es 1 lógico.
La prueba del control de calidad exige medir el tiempo en que ambos detectores están activos
en una situación de descarga brusca. Esta aplicación requiere un control por hardware del
Timer 0, de forma que se incremente durante todo el tiempo que los dos sensores permanezcan
simultáneamente activos, o sea, durante todo el tiempo que la entrada P3.2 esté a 1 lógico.
8XC251
Detector de
R Detector de
tensión P3.2
P3.2, INT0
corriente
- +
12V
En concreto, el intervalo temporal que se desea medir está comprendido entre 20ms y 30ms. Si,
por ejemplo, la frecuencia de la señal de reloj es de 12MHz, el temporizador se incrementa una
vez cada 1µs. Por tanto, 20ms se corresponden con 20.000 incrementos y 30ms se
corresponden con 30.000 incrementos. La batería pasará de forma positiva el control de calidad
siempre que el número de incrementos que haya sufrido el Timer 0, durante el tiempo en que
los dos sensores están activos, esté comprendido entre 20.000 y 30.000.
En la figura 7.14 está representado el diagrama de flujo del programa que controla el
El programa continúa con un par de instrucciones de salto condicional que tienen como
objetivo detectar el intervalo de activación simultánea de los dos sensores. Una vez que ha
finalizado la prueba, se compara el contenido de los registros del Timer 0, TH0 y TL0, con los
valores 20.000 y 30.000, para determinar si el estado de la batería es correcto.
INICIO
TMOD
TIMER 0 GATE1 C/T1 M11 M10 GATE0 C/T0 M10 M00
TEMPORIZADOR
CONTROL HARDWARE 0 0 0 0 1 0 0 1
NO
TCON
TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
SI
0 0 0 1 0 0 0 0
TIMER 0<20.000?
BATERÍA
CORRECTA
Por otra parte, un ejemplo clásico de control del Timer mediante programa es la realización de rutinas
de retardo como la explicada en el apartado 7.4.1.
Detectar el desbordamiento de los Timers es muy importante para que la aplicación funcione
correctamente.
Ejemplo 7.6 Temporización de 0.1s mediante el Timer 1
En este ejemplo se debe temporizar 0.1s utilizando el Timer 1 de un microcontrolador
8XC251Sx que funciona con un reloj de 12MHz. Con esta frecuencia de reloj el Timer 1 se
incrementa en una unidad cada microsegundo. Por tanto, para temporizar 0.1s el Timer 1 debe
incrementarse 100.000 veces. Si el Timer se programa en modo 1 y se ha cargado con el valor
inicial cero, sufre desbordamiento cuando se incrementa 216 = 65.536 veces. Una vez sufrido
desbordamiento, el Timer 1 se debe incrementar 34.464 veces más para llegar a contabilizar los
100.000 incrementos necesarios.
En la figura 7.16 está representado el diagrama de flujo del programa que controla esta
temporización. El programa comienza con instrucciones que inicializan a cero los registros del
Timer 1, TH1 y TL1. A continuación se programa adecuadamente el registro TMOD para que
el Timer 1 trabaje en modo 1, como temporizador y controlado por software (figura 7.17).
También se programa el registro TCON para poner a cero el flag de desbordamiento del Timer
1, TF1, y para habilitar su funcionamiento.
Una vez puesto en marcha el Timer, se debe detectar el momento en el que éste sufre
desbordamiento. Esto se consigue fácilmente mediante una instrucción de salto condicional: la
condición de salto debe ser el valor del flag de desbordamiento TF1. Mientras este flag está a
cero el programa ejecuta el salto de forma continuada. Cuando el Timer 1 rebasa, el flag se
pone a 1, la condición de salto ya no se cumple y por lo tanto no se efectúa dicho salto.
Llegados a este punto el Timer 1 deberá incrementarse 34.464 veces más para contabilizar los
100.000 incrementos correspondientes a un intervalo de 0.1s.
Las siguientes instrucciones del programa colocan a cero el flag de desbordamiento, detienen el
funcionamiento del Timer 1 e inicializan su contenido con el valor adecuado para que al
incrementarse 34.464 veces llegue a desbordamiento. Este valor es 216 – 34.464 =31.072d =
7960H.
INICIO TMOD
GATE1 C/T1 M11 M10 GATE0 C/T0 M10 M00
0 0 0 1 0 0 0 0
TIMER 1
TEMPORIZADOR
CONTROL SOFTWARE
Timer 1 programado en modo 1
INICIALIZAR EL
TIMER 1 CON 31.072d
TCON
TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
SI
TF1=0? 0 1 0 0 0 0 0 0
NO
Habilitación del funcionamiento del Timer 1
DETENER
EL TIMER 1
Puesta a cero del flag de interrupción del Timer 1
Fig. 7.16 Diagrama de flujo de la aplicación
Fig. 7.17 Programación y configuración del Timer 1
;******************************************************************************
; PROGRAMA DE TEMPORIZACIÓN DE 0.1s
;******************************************************************************
ORG FF:0000H ; El programa comienza en la dirección FF:0000H
MOV TH1,#00H ; Se inicializa los registros del Timer 1 a cero.
MOV TL1,#00H ;
MOV TMOD,#10H ; Se programa el Timer 1 en modo 1 como temporizador y
MOV TCON,#40H ; controlado por hardware.
SALT1: JNB TF1, SALT1 ; Se espera la activación del flag de desbordamiento TF1.
CLR TF1 ; Se pone a cero el flag TF1.
MOV TH0,#79H ; Se inicializan los registros del Timer 1 con el valor
MOV TL0,#60H ; adecuado para que rebase al incrementarse 34.464 veces.
SALT1: JNB TF1, SALT1 ; Se espera la activación del flag de desbordamiento TF1.
NOP ; Ha finalizado la temporización de 0.1s.
En la figura 7.18 se presenta el esquema de funcionamiento de los Timers 0 y 1 para los modos de
funcionamiento 0 y 1.
XTAL1 ÷12
Desbordamiento Petición de
0 interrupción
THx TLx
TFx
(8 bits) (8 bits)
1
Tx
C/Tx
TRx
Modo 0: Temporizador/contador de 13 bits
Modo 1: Temporizador/contador de 16 bits
GATEx x=0ó1
INTx
Fig. 7.18 Modos 0 y 1 para los Timers 0 y 1
En este ejemplo se trata de generar una señal cuadrada utilizando el Timer 0 programado en
modo cero, con una frecuencia de la señal de reloj de 12MHz. La función del Timer, en esta
aplicación, será la de controlar la duración del período de la onda cuadrada. La idea es
inicializar el Timer con el valor cero, ponerlo en funcionamiento y, cada vez que rebase,
complementar el valor lógico del pin P0.0, de forma que, con los sucesivos desbordamientos
del Timer 0, se genere la onda cuadrada en el pin P0.0 (figura 7.19).
8XC251
P0.0
En la figura 7.20 está representado el diagrama de flujo del programa que controla la
generación de la onda cuadrada. El programa comienza con instrucciones que inicializan a cero
los registros del Timer 0, TH0 y TL0. Seguidamente se programa adecuadamente el registro
TMOD para que el Timer 0 trabaje en modo 0, como temporizador y controlado por software.
También se programa el registro TCON para poner a cero el flag de desbordamiento del Timer
0, TF0, y para habilitar el funcionamiento del Timer 0.
Una vez puesto en marcha el Timer, se debe detectar el momento en el que sufre
desbordamiento. Esto se consigue fácilmente mediante una instrucción de salto condicional,
donde la condición de salto es el valor del flag de desbordamiento TF0. Mientras este flag esté
a cero, el programa ejecuta el salto de forma continuada. Cuando el Timer 0 rebasa, el flag se
pone a 1, la condición de salto ya no se cumple y, por tanto, el programa continúa su ejecución
por la siguiente instrucción.
INICIO
TIMER 0
TEMPORIZADOR
CONTROL SOFTWARE
SI
TF0=0?
NO
COMPLEMENTAR
P0.0
• Una rutina de servicio a la interrupción del Timer 1 que deberá incluir las instrucciones
necesarias para atender a este Timer 1 cuando interrumpa.
El programa principal deberá incluir una instrucción que habilite la fuente de interrupción del
Timer 1, poniendo a 1 lógico los bits adecuados del registro IE0 (figura 7.21). Asimismo, se
incluirányen instrucciones para programar el Timer 1 como temporizador en modo 1, para
inicializar los registros TH1 y TL1 a cero, y para habilitar su funcionamiento (figura 7.22).
IE0
;*******************************************************************************
; RUTINA DE SERVICIO A LA INTERRUPCION TIMER 1
;*******************************************************************************
ORG FF:001BH
CPL P0.0 ; Se complementa el pin P0.0.
RETI ; Retorno de RSI.
Para mejorar el diseño del ejemplo 7.8 se puede añadir un pulsador externo que controle el
funcionamiento del generador, de forma que cuando se active el pulsador, el microcontrolador
detenga la generación de la onda cuadrada, inhiba la interrupción del Timer 1 y ponga a cero el
pin P0.0. Si se aprieta de nuevo el pulsador, el microcontrolador vuelve a generar la onda
cuadrada. Si el pulsador se conecta a la entrada de interrupción /INT0, permite controlar su
activación mediante el mecanismo de interrupción (figura 7.24).
Tp
8XC251
+5V
P0.0
10 kΩ
1kΩ
INT0
4.7 µF
En concreto, se debe modificar el contenido del registro IE0 para habilitar la fuente de
interrupción /INT0, y el registro TCON para programar la interrupción /INT0 por flanco de
bajada (figura 7.25).
TCON
IE0
TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
EA EC ET2 ES ET1 EX1 ET0 EX0
0 1 0 0 0 0 0 1
1 0 0 0 1 0 0 1
Programación de /INT0 por flanco de bajada
Habilita las interrupciones
Habilita la interrupción /INT0 Habilitación del funcionamiento del Timer 1
que están a 1
Habilita la interrupción del Timer 1 Puesta a cero del flag de interrupción del Timer 1
IPH0 IPL0
b7 --- ---
b6 0 0 Bits de prioridad de la interrupción PCA
b5 0 0 Bits de prioridad de la interrupción Timer 2
b4 0 0 Bits de prioridad de la interrupción puerto serie
b3 0 0 Bits de prioridad de la interrupción Timer 1
b2 0 0 Bits de prioridad de la interrupción INT1
b1 0 0 Bits de prioridad de la interrupción Timer 0
b0 0 1 Bits de prioridad de la interrupción INT0
Por otra parte, se puede considerar que la fuente de interrupción /INT0 es más prioritaria que la
interrupción Timer 1, puesto que su activación habilita o inhibe la interrupción del Timer 1. Por
este motivo, se programa la interrupción /INT0 con un nivel de prioridad mayor que la
interrupción Timer 1. Por ejemplo, se puede programar la interrupción /INT0 con el nivel 1 y la
interrupción Timer 1 con el nivel 0.
Por otra parte, la RSI de la interrupción /INT0 debe incluir instrucciones que controlen la
habilitación de la interrupción del Timer 1 y pongan a cero el pin P0.0 si es necesario. En la
figura 7.26 está representado el flujograma de la RSI de la interrupción /INT0.
RSI /INT0
RETI
La planta que se debe controlar dispone de un sistema que neutraliza la acidez de las aguas
residuales provenientes de una planta de fabricación de papel (figura 7.27). El sistema posee un
depósito donde se mezcla el agua residual con la cantidad adecuada del componente
neutralizador, cuya función es disminuir la acidez del agua, de forma que el agua de salida del
depósito posea un pH superior a 5.5.
A1
Neutralizador Sistema
de control A2
V2
Entrada V1
de aguas
residuales S1
M
Medidor
pH
Descarga
8XC251
P1.2
A1
P1.3
A2
S1 INT0 P1.0 V1
M INT1 P1.1 V2
La estrategia que debe llevar a cabo el sistema de control para gestionar el funcionamiento de
la planta de tratamiento de aguas residuales se puede resumir en dos puntos:
• La válvula V1 debe permanecer abierta hasta que el sensor S1 se active, en cuyo caso se
cerrará durante treinta segundos. Si una vez pasado este tiempo el sensor S1 sigue
activo, se repetirá la operación de cierre de la válvula V1. Mientras V1 esté abierta, el
indicador A1 permanecerá encendido; en caso contrario el indicador parpadeará.
• La válvula V2 debe estar cerrada hasta que se active el sensor M, en cuyo caso se abrirá
durante cinco segundos. Una vez transcurrido ese tiempo, si el sensor M continúa activo,
se repetirá la operación de apertura de la válvula V2. El indicador A2 se activa cuando
la válvula V2 está abierta y parpadea cuando está cerrada.
Los recursos utilizados para resolver esta aplicación son cuatro:
• La interrupción externa /INT0, que se encarga de detectar la activación del sensor S1.
La interrupción se activa por nivel para que pueda ser atendida por la CPU mientras el
sensor S1 se encuentre a uno lógico.
• La interrupción externa /INT1, cuya función es detectar la activación del medidor de
pH. Esta interrupción también se programa por nivel por el mismo motivo que la /INT0.
• El Timer 0, que se encarga de temporizar el intervalo de 30s, tiempo que debe
permanecer abierta la válvula V1 cuando se active S1.
• El Timer 1, que se encarga de temporizar los 5s de apertura de la válvula V2.
• El programa está compuesto de una rutina principal y de cuatro rutinas de atención a la
interrupción, una para cada fuente de interrupción utilizada en la aplicación.
La función del programa principal será básicamente la de habilitar y programar los niveles de
prioridad de las diversas fuentes de interrupción utilizadas, así como la de ejecutar la secuencia
de parpadeo de los indicadores luminosos A1 y A2.
Para habilitar las cuatro fuentes de interrupción utilizadas, se ponen a uno lógico los bits
correspondientes del registro habilitador de interrupciones IE0: EX0, ET0, EX1 y ET1. Esto se
consigue cargando en el registro IE0 el valor 8FH (10001111b).
Por otra parte, se deben poner a uno lógico los bits IT0 e IT1 del registro TCON, con el
objetivo de que las interrupciones externas /INT0 e /INT1 se activen por nivel. Esto se
consigue almacenando en el registro TCON el valor 0AH (0000 1010b).
Por último, se debe poner el bit INTR del byte de configuración CONFIG1 a uno lógico. De
esta forma, cuando la CPU ejecute una interrupción, se cargarán en la pila, automáticamente,
los tres bytes del contador de programa, PC, y el registro de estado, PSW1.
En cuanto a la rutina de retardo, que se utiliza para temporizar el parpadeo de los indicadores
luminosos, estará compuesta de dos bucles anidados basados en decrementar los registros R0 y
R1. Modificando el valor de los registros R0 y R1 se puede variar el tiempo de ejecución de la
rutina y, por tanto, la frecuencia de parpadeo. Para calcular el tiempo de retardo hay que
determinar el número de veces que se ejecuta cada instrucción, así como el tiempo que tarda en
ejecutarse cada una de ellas.
PRINCIPAL RETARDO
INICIALIZAR: R0 = 10H
IE0 = 8FH
TCON = 0AH
IPH0 = 03H
IPL0 = 03H R1 = FFH
P1.2 = 1 DECREMENTA R1
P1.3 = 1
NO
RETARDO R1 = 0?
SI
P1.2 = 0
DECREMENTA R0
P1.3 = 0
RETARDO NO
R0 = 0?
SI
RET
Fig. 7.29 Flujograma del programa principal y de la rutina de retardo
En la RSI del Timer 0 se debe contar el número de rebasamientos que sufre este temporizador. Cuando
el Timer 0 rebase un número de veces equivalente a 30s se abrirá la válvula V1, se detendrá el
funcionamiento del Timer 0 y se habilitará de nuevo la interrupción /INT0, de forma que si el sensor
S1 continúa activo se repetirá de nuevo la secuencia de cierre de V1.
INT0 T0
CERRAR VÁLVULA V1 NO
T = 30s?
SI
INICIALIZAR T0
PARAR T0
ACTIVACIÓN T0
ABRIR VÁLVULA V2
INHIBIR INT0
BORRAR IE0
RETI
HABILITAR INT0
RETI
Fig. 7.30 Flujogramas de las rutinas de servicio a las interrupciones /INT0 y Timer 0
Las rutinas de atención a las interrupciones /INT1 y Timer 1 tienen funciones similares a las
interrupciones /INT0 y Timer 0. En la figura 7.31 se presentan los flujogramas
correspondientes a ambas rutinas.
INT1 T1
ABRIR VÁLVULA V2 NO
T = 5s?
SI
INICIALIZAR T1
PARAR T1
ACTIVACIÓN T1
CERRAR VÁLVULA V2
INHIBIR INT1
BORRAR IE1
RETI
HABILITAR INT1
RETI
Fig. 7.31 Flujogramas de las rutinas de servicio a las interrupciones /INT1 y Timer 1.
A continuación se presentan el listado del programa principal y de la rutina de retardo.
;****************************************************************************
; VECTORIZACION INTERRUPCIONES
;****************************************************************************
ORG FF:0003H ; Vector de interrupción de /INT0.
JMP RSI_INT0
ORG FF:000BH ; Vector de interrupción del Timer 0.
JMP RSI_T0
Para temporizar los treinta segundos se inicia el Timer 0 para que tarde 0.5s en rebasar, de
forma que se deben contabilizar 60 rebasamientos en la RSI del Timer 0 para abrir de nuevo la
válvula V1. Para temporizar 0.5s, con una frecuencia de reloj de 1.2MHz, el Timer 0 debe
incrementarse 50.000 veces (C350H); luego se ha de cargar dicho Timer con la combinación
resultante de restar a FFFFH el valor C350H:
;*****************************************************************************
; RUTINA DE SERVICIO A LA INTERRUPCION TIMER 0
;*****************************************************************************
ORG FF:0400H
RSI_T0: INC R3 ; Se incrementa el contador de rebasamientos.
CMP R3,59d ; Se compara el número de rebasamientos con 59.
JNC SIGUE ; Si el número de rebasamientos es menor o igual que 59 continúa temporizando.
CLR TR0 ; En caso contrario se detiene el Timer 0 y
CLR P1.0 ; se abre la válvula V1.
SETB EX0 ; Se habilita de nuevo la interrupción /INT0.
CLR IE0 ; Se borra el flag de la interrupción /INT0.
SIGUE: RETI ; Retorno al programa principal.
;****************************************************************************
; RUTINA DE SERVICIO A LA INTERRUPCION INT1
;*****************************************************************************
ORG FF:0500H
RSI_INT1: SETB P1.1 ; Se abre la válvula V2.
SETB TMOD.4 ; Se programa el Timer 1 en modo 1.
MOV TH1,#3CH ; Se inicializa el Timer 1 para temporizar 0.5 s.
MOV TL1,#AFH
MOV R4,#00H ; El registro R4 contará los rebasamientos del Timer 1.
SETB TR1 ; Puesta en marcha del Timer 1.
CLR EX1 ; Se inhibe la interrupción /INT1
RETI
;**************************************************************************
; RUTINA DE SERVICIO A LA INTERRUPCION TIMER 1
;**************************************************************************
ORG FF:0600H
RSI_T1: INC R4 ; Se incrementa el contador de rebasamientos
CMP R4,09d ; Se compara el número de rebasamientos con 9
JNC SIGUE1 ; Si el número de rebasamientos es menor o igual que 9
; continua temporizando.
CLR TR1 ; Se detiene el Timer 1
SETB P1.1 ; Se abre la válvula V2
SETB EX1 ; Se habilita la interrupción /INT1
CLR IE1 ; Se borra el flag de la interrupción /INT1
SIGUE1: RETI ; Retorno al programa principal
XTAL1 ÷12
Petición de
0 interrupción
TLx Desbordamiento
TFx
(8 bits)
1
Tx
C/Tx
Recarga
TRx
THx
GATEx (8 bits)
INTx x=0ó1
Fig. 7.32 Modo 2 de autorrecarga de los Timers 0 y 1
En este modo de trabajo cuando el Timer sufre desbordamiento se activa el flag TFx y
automáticamente se carga el contenido del registro THx en el registro TLx, de forma que el Timer
comienza a contar a partir del valor cargado en el registro THx. El proceso de recarga no modifica el
contenido del registro THx. En la figura 7.32 está representado el esquema del Timer 0 o de Timer 1
funcionando en modo 2.
+5V INT1
P0.0
P0.1 Salida de
P0.2 cuenta: 3-15
Entrada P0.3
de cuenta T1
El valor elegido para inicializar los registros del Timer 1 es el F3H, de forma que al volcar este
contenido sobre el puerto P0, en los cuatro bits de menor peso aparece el valor 3H (valor inicial
de cuenta). A medida que el Timer 1 se incrementa se puede seguir el incremento a través del
puerto P0. Cuando se llega al valor FH (15d) y se recibe un nuevo pulso se produce
desbordamiento y el registro TL1 se carga de nuevo con F3H (figura 7.35).
Desbordamiento
INICIO
TIMER 1
CONTADOR
CONTROL HARDWARE
CARGAR TL1 EN P0
En este modo de funcionamiento, el registro TL0 utiliza todos los bits de control del Timer 0 para su
funcionamiento normal: C/T0, GATE0, TR0 y TF0.
En cambio, las prestaciones de funcionamiento del registro TH0 se ven muy reducidas debido a que
los únicos flags que controlan su funcionamiento son el TR1 y el TF1. El flag TR1 permite habilitar el
funcionamiento del registro TH0 y el flag TF1 se activa cuando este registro sufre desbordamiento.
Por otra parte, el registro TH0 sólo puede operar como temporizador y no como contador (figura
7.37).
T0
C/T0
TR0
Petición de
Desbordamiento interrupción
GATE0
TH0
1/12 Fosc TF1
(8 bits)
INT0
TR1
Fig. 7.37 Modo 3 del Timer 0, dos Timers de 8 bits
Por este motivo, cuando el Timer 0 está programado en modo 3, el Timer 1 no puede utilizar los flags
TR1 y TF1 para su normal funcionamiento. Esto significa que cuando el Timer 1 desborde no se
activará el flag TF1; igualmente, no se puede utilizar el bit TR1 para habilitar el funcionamiento de
este Timer.
Por otra parte, cuando el Timer 1 se programa en modo 3 se detiene su funcionamiento. Este modo
puede utilizarse para detener el Timer 1 cuando el Timer 0 esté programado en modo 3 y el bit TR1 no
esté disponible.
7.6 Timer 2
Número Nombre
Función
de bit del bit
7:2 -- Reservado.
Estos bits están reservados para futuras aplicaciones y no se pueden utilizar.
1 T2OE Bit de habilitación del Timer 2.
Cuando el Timer 2 trabaja en modo Clock-out, este bit conecta la salida de reloj con el
pin T2.
0 DCEN Bit de cuenta atrás.
Este bit configura al Timer 2 como un contador ascendente o descendente.
Número Nombre
Función
de bit del bit
7 TF2 Flag de desbordamiento del Timer 2.
Este flag se pone a 1 cuando el Timer 2 sufre desbordamiento, o sea, cuando pasa de
la combinación todo unos a la combinación todo ceros. Este bit no se activa si
RCLK=1 o TCLK=1.
6 EXF2 Flag externo del Timer 2.
Este flag se pone a 1 cuando se produce un flanco negativo en el pin T2EX con el flag
EXEN2=1.
5 RCLK Bit de reloj en recepción.
Este flag se pone a 1 cuando el Timer 0 sufre desbordamiento, o sea cuando pasa de la
combinación todo unos a la combinación todo ceros.
4 TCLK Bit de reloj en transmisión.
3 EXEN2 Bit de habilitación externa del Timer 2.
Cuando este bit está a 1 y se produce una transición negativa en el pin T2EX, se
produce una recarga o captura, a menos que el Timer 2 se utilice como generador de
Baud Rate del puerto de comunicación serie. Si el bit EXEN2 está a cero se ignoran
las transiciones en el pin T2EX.
2 TR2 Bit de puesta en marcha del Timer 2.
Cuando está a 1 lógico el Timer 2 está habilitado para funcionar; en caso contrario
esta parado.
1 C/T2 Bit de selección de contador/temporizador:
C/T2 = 0: el Timer 2 funciona como temporizador.
C/T2 = 1: el Timer 2 funciona como contador.
0 CP/RL2 Bit de captura/recarga.
Cuando este bit está a 1 se produce una captura al aplicar un flanco negativo en la
entrada T2EX con EXEN2=1. Cuando este bit está a cero se produce un recarga al
aplicar un flanco negativo en la entrada T2EX con EXEN2=1. Si RCLK=1 o
TCLK=1, se ignora el bit CP/RL2 y se fuerza la recarga del Timer 2 cuando sufre
desbordamiento.
Los bits de los registros T2MOD y T2CON permiten programar el modo de funcionamiento de los
Timers, controlar su puesta en marcha, programar su modo de operación (contador o temporizador) y
detectar el desbordamiento. En la tabla 7.12 se indican los cuatro modos de operación en los que
puede funcionar el Timer 2.
Si el bit EXEN2 está a 1 lógico, un flanco de bajada en el pin T2EX captura el valor actual de los
registros del Timer 2, TH2 y TL2, en los registros RCAP2H y RCAP2L respectivamente. Al mismo
tiempo, el flanco de bajada en el pin T2EX produce la activación del bit EXF2, lo cual genera una
petición de interrupción al microcontrolador.
Desbordamiento
XTAL1 ÷ 12 0
TH2 TL2
TF2
(8 bits) (8 bits)
1
T2
TR2
C/T2
Petición de
interrupción
RCAP2H RCAP2L
T2EX EXF2
EXEN2
Si EXEN2=1, los registros del Timer se recargan por dos motivos distintos: cuando se produce
desbordamiento y cuando se aplica un flanco de bajada en el pin T2EX. El flanco de bajada en T2EX
también activa el bit EXF2, que realiza una petición de interrupción al microcontrolador.
T2 TR2
C/T2
Recarga
RCAP2H RCAP2L
TF2 Petición de
interrupción
T2EX
EXF2
EXEN2
Fig. 7.39 Modo autorecarga del Timer 2 con DCEN = 0
FFH FFH
Complemento
XTAL1 ÷12 EXF2
Petición de
0 Desbordamiento interrupción
TH2 TL2
TF2
(8 bits) (8 bits)
T2 1
C/T2 TR2
Dirección de cuenta
1 = ascendente
T2EX 0 = descendente
RCAP2H RCAP2L
Cuando T2EX vale 0 lógico, el Timer 2 cuenta hacia abajo. El desbordamiento del Timer 2 ocurre, en
este caso, cuando el contenido de los registros TH2 y TL2 es igual al valor cargado en los registros
RCAP2H y RCAP2L, respectivamente. El desbordamiento provoca la activación del flag TF2 y
recarga los registros del Timer con el valor FFFFH.
Por otra parte, cuando el Timer sufre desbordamiento, en la cuenta ascendente o descendente, el bit
EXF2 cambia de valor. En este modo de funcionamiento el bit EXF2 no genera ninguna petición de
interrupción al microcontrolador y puede utilizarse como bit 17 del Timer 2.
T2
TR2
C/T2
RCAP2H RCAP2L
÷2
T2OE
Petición de
interrupción
T2EX EXF2
EXEN2
Fig. 7.41 Timer 2: modo generación de reloj
La frecuencia de la señal de reloj que se genera con este modo se puede programar adecuadamente
fijando el valor de los registros RCAP2H y RCAP2L:
FOSC
Frecuencia reloj = (7.1)
4 ⋅ ( 65535 − RCAP 2 H , RCAP2 L )
Si el microcontrolador funciona con un reloj de 16MHz, se podrá programar un rango de frecuencias
de 61Hz a 4MHz. La señal de reloj, generada en este modo, está disponible en el pin T2.
Para programar el Timer 2 en el modo Clock-out se debe poner a 1 lógico el bit T2OE del registro
T2MOD. También se debe poner a cero lógico el bit C/T2, para que el Timer 2 funcione como
temporizador y para habilitar al mismo tiempo el pin T2 como salida de reloj. Los registros RCAP2H
y RCAP2L se inicializan adecuadamente, según la expresión 7.1, para fijar la frecuencia de la señal
generada. Por otra parte, los registros TH2 y TL2 se cargan con el mismo valor, o con otro distinto,
dependiendo de la aplicación. Finalmente, se activa el bit TR2 para poner en marcha el Timer 2.
Es posible utilizar el Timer 2 como generador de baudios y como generador de reloj de forma
simultánea.
A JE
G AR
S1 S3 S2
Sistema
de control
8XC251 R S Q+
S1 R Q T2EX
0 0 Q
S2 S 0 1 1
1 0 0
S3 T2 1 1 X
Fig. 7.43 Conexión de los sensores al µC 8XC251Sx y tabla de funcionamiento de una báscula RS
En esta aplicación, el Timer 2 debe trabajar como contador bidireccional; se deberá programar,
por tanto, en modo autorrecarga con DCEN=1. Para ello se deben inicializar los siguientes bits:
RCLK = TCLK = 0, CP/RL2 = 0, T2OE = 0 y el bit DCEN = 1. Los bits RCLK, TCLK y
CP/RL2 están ubicados en el registro T2CON, mientras que el bit T2OE y DCEN están
ubicados en el registro T2MOD. Seguidamente se deben inicializar los registros del Timer 2 a
cero, y ponerlo en marcha.
;********************************************************************************
; PROGRAMA DE CONTROL DEL GARAJE
;********************************************************************************
ORG FF:0000H ; El programa está almacenado a partir de la dirección de memoria FF:0000H
CLR RCLK ; Se pone a cero el bit RCLK del registro T2CON.
CLR TCLK ; Se pone a cero el bit TCLK del registro T2CON.
CLR CP/RL2 ; Se pone a cero el bit CP/RL2 del registro T2CON.
CLR T2OE ; Se pone a cero el bit T2OE del registro T2MOD.
SETB C/T2 ; Se programa el Timer 2 como contador.
SETB DCEN ; El Timer 2 trabaja como contador Up/Down
SETB TR2 ; Se habilita el funcionamiento del Timer 2.
MOV TL2,#00H ; Se inicializa el contador a cero.
MOV TH2,#00H ;
Los microcontroladores de la serie 8XC251Sx contienen un Timer watchdog, WDT, que genera un
reset automático del microcontrolador si pasa un cierto tiempo sin recargar el contenido de este Timer.
La utilidad del WDT es la de posibilitar el reset del microcontrolador en casos de funcionamiento
inadecuado del programa.
Una vez habilitado para funcionar, el Timer WDT se incrementa cada 12 períodos de señal de reloj y,
si no se borra, sufre desbordamiento cuando llega a la combinación 3FFFH+1; entonces genera,
además, un reset al microcontrolador 8XC251Sx.
Si, por ejemplo, la frecuencia de reloj del microcontrolador es de 16MHz, el ciclo de periférico es de
750ns y el Timer WDT desborda en 750ns x 16384 = 12,288ms.
Para borrar el Timer WDT se debe escribir en el registro WDTRST una secuencia de dos bytes: 1EH y
1EH. Esta operación habilita y borra el Timer WDT, de forma que comienza de nuevo a incrementarse
a partir del valor inicial 0000H. A lo largo del programa se deberá escribir la secuencia de dos bytes
para borrar y habilitar de nuevo el Timer WDT antes de que desborde.