Вы находитесь на странице: 1из 15

4.

2 Temporizador/Contador
Los temporizadores/contadores son probablemente los perifricos complejos de
mayor uso en los microcontroladores. Los temporizadores/contadores son
altamente verstiles, se pueden emplear para medir periodos de tiempo, para
determinar el ancho de un pulso, para medir una velocidad, para medir frecuencia,
o para proporcionar seales de salida. Ejemplos de aplicaciones pueden incluir la
medicin de las revoluciones por minuto de un motor de automvil, el periodo exacto
de un tiempo especfico, tal como el tiempo de trayectoria de una bala, producir
tonos para crear msica o para producir la chispa de una buja de un sistema de
ignicin, o proveer el ancho especifico de un pulso u obtener frecuencias especficas
para el control de la velocidad de un motor.

Un temporizador o timer, es un reloj especializado, que regularmente se ocupa para


controlar la secuencia de un evento o proceso.

Un contador es en trminos generales, un dispositivo que almacena el nmero de


veces que un evento se lleva a cabo.

Una labor habitual de los controladores suele ser la determinacin de


intervalos de tiempo concretos.
Esto se hace a travs de un elemento denominado Temporizador (Timer).
Un temporizador bsicamente es un registro de n-bits que se incrementa de
manera automtica en cada ciclo de instruccin o cuando ocurre un evento
externo.
Si la fuente de temporizacin es externa, se le conoce como contador de
eventos.
El registro puede ser pre-cargado para iniciar su conteo a partir de un valor
determinado.
Cuando ocurre un desbordamiento en el registro (una transicin de 1s a 0s)
se genera alguna sealizacin.
En el caso de los microcontroladores AVR, pueden generarse
4.2.1 Configuracin y programacin como temporizador.

La operacin del Timer0 se controla a travs del registro OPTION_REG . En el


modo temporizador (T0CS=0), se produce un incremento del registro TMR0 cada
ciclo de instruccin (prescaler asignado al perro guardin WDT). Si se escribe en el
registro TMR0, no se produce el incremento durante los dos siguientes ciclos de
instruccin; este hecho debe tenerse muy en cuenta por parte del usuario y, de ser
necesario, ajustar el valor escrito en TMR0.
El TMR0 tiene las siguientes caractersticas:

se puede leer y escribir


puede trabajar con reloj externo o interno
detecta el flanco de subida o bajada del reloj externo
tiene un prescaler de 8 bits
tiene una interrupcin por desborde de la cuenta de 255 a 0

los registros asociados a el son el TMR0, INTCON y el OPTION_REG

El bit T0CS (OPTION 2) a 1 trabaja como temporizador, 0 trabaja como contador

El bit T0SE (OPTION 4) en modo contador a 1 flanco descendente, 0 flanco


ascendente

El bit PSA (OPTION 3) 0 prescaler al temporizador, 1 prescaler al perro guardian


WDT

Cuando se desborda el TMR0, se activa el bit 2 de INTCON (T0IF) y si el T0IE esta


activado el T0IF generara interrupcin y se debe borrar por software cuando se
atienda la interrupcin

Para calcular el tiempo de temporizacin


Configurators el OPTION_REG

BANKSEL OPTION_REG

MOVLW B'00000000'

ANALICEMOS

BIT 7 Pull up PORTB Disable


BTI 6 interrupcion por flaco de subida en el INT Pin
BIT 5 fuente del clock para el TMR0, internal 1 ciclo ed intruccion (1/Fosc)
BIT 4 Flanco de bajada para el incremento del TMR0
BIT 3 Prescaler asignado al TMR0
BIT 2-0 Division del prescaler
Configuramos el INTCON

Registro donde activamos las interrupciones globales y la del TMR0

MOVLW B'10100000'

MOVWF OPTION_REG

BIT 7 Activamos las interrupciones Globales


BIT 6 interrupciones de otros perifericos desactivadas
BIT 5 Habilitamos la interrupcion por desborde en el TMR0
BIT 4 desabilitamos interrupcion externa INT
BIT 3 desabilitamos interrupcion por cambio en el PORTB
BIT 2 bandera interrupcion en TMR0
BIT 1 bandera interrupcion en INT
BIT 0 bandera interrupcion por cambio en PORTB
4.2.2 Configuracin y programacin como contador.

En el modo contador (T0CS=1), se produce un incremento por cada transicin


ascendente (T0SE=0) o descendente (T0SE=1) en el pin RA4 del Timer0.

Para manejar la TMR0, el PIC utiliza 2 registros, estos son:

TMR0 (01h): Este es el contador propiamente dicho y puede ser ledo y escrito

en cualquier momento.

OPTION (81h): De este registro, utilizaremos los siguientes bits:


T0CS: Indica cual es el origen de los pulsos de clk para el timer; si es 1
el origen es la seal introducida por el pin RA4/T0CKI, si es 0 el origen
ser el ciclo de instruccin (CLKOUT = FrecuenciaXtal/4).
T0SE: Indica el flanco por el que se incrementar la cuenta del contador
TMR0. Si vale 0 se har por el flanco de bajada, si es 1 se har por el
flanco de subida.
PSA: El chip tienen internamente un divisor, este se puede asignar
mediante este bit al WDT con un 1 o al TMR0 con un 0.
PS2:PS0: Este es el valor de la preescala del divisor, segn la siguiente
tabla de valores.

El TMR0 puede funcionar de dos maneras; como contador de eventos o como


temporizador. Para seleccionar de que manera queremos que funciones utilizamos
el bit T0CS del registro OPTION_REG.

Cuando seleccionamos TMR0 como contador de eventos, mediante el pin T0SE


indicamos porque flanco, de subida o bajada, en la seal aplicada en el pin
RA4/T0CKI, queremos que se incremente el contador.

La seal que lleva al TMR0 la podemos preescalar mediante un divisor, este divisor
lo podemos asignar tanto al WDT como al TMR0 mediante el bit PSA del
OPTION_REG. El valor del rango del divisor viene determinado por los bit PS2:PS0
segn la tabla anterior.

El TMR0 es capaz de realizar una interrupcin cada vez que pasa de 255 a 0, para
permitirla hay que poner a 1 el bit T0IE del registro INTCON y el flag de la
interrupcin es el T0IF del registro INTCON.

El valor de TMR0 se inicializa con ValIni (250), con lo que cada 6 pulsaciones en la
tecla conectada al pin RA4/T0CKI, el TMR0 pasara de 255 a 0, generando una
interrupcin que incrementara el valor del contador formado por los leds conectados
al PORTA.
Lo nico a destacar es la programacin del OPTION_REG para configurar el TMRO.
Veamos dos ejemplos:

OPTION_REG = b11111000 : Con este valor hacemos T0CS=1 (


pone el timer en modo contador de eventos), T0SE=1 ( el contador se
incrementar con el flanco de bajada de la seal el RA4/T0CKI),
PSA=1 ( el divisor esta asignado al WDT por lo que el ratio de la seal
ser 1:1). Con esta configuracin se necesitarn 6 pulsos para
incrementar el valor de los leds.
OPTION_REG = b11110000 : Con este valor hacemos T0CS=1 (
pone el timer en modo contador de eventos), T0SE=1 ( el contador se
incrementar con el flanco de bajada de la seal el RA4/T0CKI),
PSA=0 ( el divisor esta asignado al TMR0 por lo que el ratio de la seal
vendr determinado por el valor de PS2:PS0, como es 000 el rango
ser 1:2). Con esta configuracin se necesitarn 12 pulsos para
incrementar el valor de los leds. Puedes probar diferentes valores de
OPTION_REG, para estudiar ms en profundidad el funcionamiento
del TMR0.

Si utilizamos el TMR0, junto con el divisor, como temporizador podremos medir


periodos de tiempo muy precisos, hacer periodos de espera o generar seales de
tipo PWM.

4.2.3 Desarrollo de aplicaciones

Timer0_1.c: Cada vez que se acte sobre el pulsador conectado en el pin RA4 se
incrementa un contador que se visualiza en el LCD.
Cuando este mdulo trabaja como temporizador cuenta los ciclos de instruccin (sin
prescaler) o los ciclos que recibe del prescaler. Como es un contador ascendente el
TMR0 debe ser cargado con el valor de los ciclos que se desean contar restados de
256 que es el valor de desbordamiento. Por ejemplo, para contar 28 ciclos (de
instruccin/prescaler), se carga el TMR0 con 228 (256-28). El ciclo de instruccin
tiene una duracin de 4us para una frecuencia de oscilador de 1MHz (PIC16F88).
Sin prescaler medira un tiempo de 28x4x1us = 112us. Con un prescaler 1:8, el
tiempo medido sera 28x4x8us = 896us. De manera general, el intervalo de
temporizacin T se puede calcular con la siguiente frmula:

T=N x TCI x n
Donde:

N = nmero de ciclos de instruccin/prescaler

TCI = perodo del ciclo de instruccin

n = valor del prescaler

Mientras que el valor de carga Q del TMR0 se calcula as:

Q=256-N

Para medir 500us, con un prescaler 1:1 (prescaler asignado al perro guardin WDT)
y un TCI = 4us se necesitan 500/4 = 125 ciclos de instruccin. El valor inicial del

Ejemplo 2

TMR0 debe ser 131 (256-125).

T0CON: el ms importante de cara a la configuracin del timer:

T0CON.TMR0ON (bit 7) -> arranca(1) o para (0) el TIMER

T0CON.T08bit (bit 6) -> selecciona modo 8 bits (1) o 16 bits (0)

T0CON.T0CS (bit 5) -> selecciona modo TIMER (0) o contador externo (1)

T0CON.T0SE (bit 4) -> en caso de contador externo decide si cuenta en


flanco subida (0) o bajada (1).

T0CON.PSA (bit 3) -> uso (0) o no (1) de un divisor (prescaler) previo.

T0CON.PS0-2 (bits 0-2) -> bits que definen el valor del divisor previo, desde 1:2
(000) hasta 1:256 (111)

TMR0L y TMR0H: permiten acceder (lectura/escritura) al valor del contador (TMR0L


para el byte menos significativo y TMR0H para el ms significativo).
INTCON: bits para activar la interrupcin asociada al Timer0 (ver la entrada sobre
interrupciones).

Las decisiones importantes de cara a la configuracin del timer son:

Uso de contador de 8 o 16 bits. Si se escoge 8 bits solo se usa TMR0L como


contador y obviamente se resetear cada 256 incrementos. Esto es importante
tambin de cara a las posibles interrupciones asociadas, ya que la interrupcin del
TIMER0 se produce al pasar por 0 el contador.

Si queremos hacer ms lento el contador podemos usar el prescaler, que no


es ms que un divisor previo que hace que slo se cuenten 1 de cada N ciclos. N
puede ser 1 (sin prescaler), 2, 4, 8, etc. En ese caso hay que poner a 0 el bit PSA
(usar PRESCALER) y poner el valor correspondiente en los bits asociados. La
frmula es simplemente que divisor N deseado ser = 2^(bits_PS+1).

Una vez en marcha el timer podemos consultar su valor accediendo a los registros
TMR0L y TMR0H. El byte alto TMR0H no es el verdadero byte alto del contador sino
un buffer de dicho valor. La razn de esto es asegurar la consistencia al hacer
lecturas/escrituras de un contador de 16 bits en un procesador de 8 bits. Siempre
habra la

posibilidad de que entre la lectura de TMR0L y la de TRMR0H el contador se


actualizase invalidando la lectura.

La solucin es hacer que una lectura de TMR0L cause una copia simultnea del
byte alto del contador a TMR0H. De la misma forma una escritura de TMR0L causa
la escritura simultnea de TMR0H al byte alto del contador.

Consecuencias para nosotros? Si queremos leer el valor del timer (16 bits)
debemos siempre leer primero TMR0L y luego TMR0H. En la escritura es lo
contrario, primero escribimos TMR0H (lo que no tiene ningn efecto sobre el
contador, ya que TMR0H es un buffer) y luego TMR0L (momento en el que TMR0L
y lo que tuviramos en TMR0H se vuelcan al contador. Podramos definir una macro
o funcin para no tener que estar pendientes. Por ejemplo, para escribir el valor de
TMR0 (16 bits) haramos:

Como vemos primero fijamos TMR0H (con la parte alta de x) y luego TMR0L.
Igualmente podramos definir algunas macros para arrancar/parar el timer sin tener
que acordarnos de los bits involucrados como hicimos con las interrupciones:

En el main(), configuraremos el timer en modo 16 bits con un prescaler de 256, lo


que supone que se incrementa cada 256 x 0.2 usec (@20 Mhz), esto es, cada 51.2
usec ms o menos. Con la macro set_TMR0 inicializamos el contador y con
start_TMR0 arrancamos el reloj. Durante el bucle (cada 10,000 ciclos = 2 msec)
mostramos el contenido de TMR0L y TMR0H en PORTB y PORTC
respectivamente.
Al ejecutarse PORTB se ve esttico, ya que cambia demasiado rpido (50 usec)
para poder ser apreciado. En cambio en PORTC (el byte alto del timer) si se aprecia
el incremento. PORTC se incrementa cada 256 x 51.2 usec, es decir, unos 13 msec.
Cada vez que se actualiza los datos (2 msec) PORTC habr cambiado en unas 6/7
unidades.

Trs un rato (65536 x 2 msec = 128 sec) las lucecitas se detienen, ya que el contador
cont da la vuelta completa y la condicin establecida (cont==0) detiene el timer.

Como otros compiladores, C18 tiene algunas rutinas para facilitar el manejo de los
timers:

OpenTimer0 -> da valores a T0CON a travs de mascaras predefinidas.

Tambin pone a 0 el contador y lo pone en marcha.

CloseTimer0 -> desactiva el contador TMR0 y su interrupcin asociada.

WriteTimer0 -> equivalente a la macro set_TMR0()

Abajo se lista el mismo programa usando estas rutinas. Algunos comentarios sobre
los cambios:

Es preciso incluir <timers.h> para tener acceso a las declaraciones de las funciones
usadas

No es necesario resetear el contador ni arrancarlo explcitamente (lo hace


OpenTimer0)
Las mscaras de configuracin se combinan con AND. Es posible combinarlas con
OR definiendo previamente #define USE_OR_MASKS en el programa. Esto afecta
a las opciones que se establecen por defecto. En el modo AND el valor por defecto
de los bits es 1 (modo 8 bits, contador de pulsos en un pin, etc.). En modo OR el
valor por defecto es 0 (16 bits, contador de reloj).

Obviamente es ms cmodo y legible usar OpenTimer que dar valores directamente


a T0CON. Sin embargo conocer los detalles siempre es interesante por si lo que
queremos hacer no se puede hacer exactamente con las rutinas suministradas. Por
ejemplo, closeTimer0() no slo para el contador sino que desactiva la interrupcin
asociada, por lo que no es exactamente equivalente a nuestra macro stop_TMR0.
Las llamadas a funciones son ms costosas que una macro, por lo que en ciertas
aplicaciones crticas son preferibles, etc. Como siempre es una cuestin de usar lo
ms conveniente en cada caso (pero para ello hay que conocer las posibilidades).

Вам также может понравиться