0% encontró este documento útil (0 votos)
115 vistas

Timer 2

Este documento introduce el uso del Timer 2 en Arduino. Explica que el Timer 2 es un contador hardware de 8 bits que puede usarse para tareas como medición de tiempos y generación de ondas. Describe cómo configurar el Timer 2 en modo normal para generar interrupciones periódicas a diferentes frecuencias usando un prescaler. También muestra código de ejemplo para conmutar un pin digital usando interrupciones del Timer 2 y para ejecutar tareas múltiples a diferentes frecuencias basadas en unidades de tiempo de 1 ms.

Cargado por

PierDonnee
Derechos de autor
© © All Rights Reserved
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
115 vistas

Timer 2

Este documento introduce el uso del Timer 2 en Arduino. Explica que el Timer 2 es un contador hardware de 8 bits que puede usarse para tareas como medición de tiempos y generación de ondas. Describe cómo configurar el Timer 2 en modo normal para generar interrupciones periódicas a diferentes frecuencias usando un prescaler. También muestra código de ejemplo para conmutar un pin digital usando interrupciones del Timer 2 y para ejecutar tareas múltiples a diferentes frecuencias basadas en unidades de tiempo de 1 ms.

Cargado por

PierDonnee
Derechos de autor
© © All Rights Reserved
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 5

Timer 2: Introducción 

El microcontrolador de las placas Arduino dispone de 3 módulos Contador/Timers (dos de 8 bits y uno de 16 bits). Se
trata de hardware independiente al microprocesador que puede ejecutar tareas paralelas sin detener el flujo del
programa. Algunas de éstas tareas son contador, medida precisa de tiempos, generador de ondas, .... Estos Timers
son usados internamente por el core de Arduino para sus funciones internas, como pueden ser millis, delay,
analogWrite,...

Aquí vamos a ver cómo trabajar con el Timer 2, el cual es de 8 Bits. El Timer 2 es usado internamente en el core
Arduino para generar el PWM por los pines 3 y 11, por lo que no se podrá usar dicha función en conjunto con el
código propuesto más adelante.

Para empezar vamos a ver el funcionamiento de dicho contador en modo Normal (Normal mode).
Se trata del modo más sencillo, en el cual el el contador se incrementa a cada pulso de reloj  hasta llegar a su
máximo (8 bits=255) y se reinicia de nuevo desde 0. Es decir 0,1,2,...255 -> 0,1,...,255 -> 0,1,...
En el momento que el contador vuelve a 0 (registro TCNT2), se activa el  flag de  "overflow" (TOV2).  Se puede
configurar una interrupción (overflow del timer) cuando ésto ocurre. Dicha interrupcion se encarga de resetear
dicho el flag.

Notas:
El flag es un bit que cambia su estado, como si fuera una "alarma" para avisar al programador que un evento ha
ocurrido. Dicho bit (TOV2) de overflow se encuentra en el registro TIFR2.
Una interrupción es una señal recibida por el microcontrolador, que interrumpe la ejecución del código actual y
cambia a la rutina que atiende dicha interrupción.

Normalmente el cristal usado en la mayoría de las placas Arduino es de 16 MHz (cuidado que algunas como LilyPad
van a 8Mhz), lo que significa que la resolución máxima es de 1/16.000.000= 62.5 ns. Es decir, que el contador
alimentado por la frecuencia reloj del micro, incrementa en uno su valor cada 62.5 ns, y tendría su overflow cada
256*1/16000000=0.016ms.

Se puede observar que es un tiempo muy pequeño. Para poder tener más rangos, el timer dispone de PRESCALER.
Ésto es simplemente un divisor de la frecuencia del reloj que le esta alimentando al timer. Los PRESCALER
disponibles son 1,8,32,64,128,256 y 1024.

El lenguaje Arduino no dispone de funciones propias para configurar los timer. Los registros internos del
microcontrolador para configurar el Timer2 son TCCR2A, TCCR2B, TNT2, OCR2A,OCR2B, TIMSK2,TIFR2,ASSR y
GTCCR. Lo mejor para ampliar conocimientos acerca de todas las posibilidades que existen es el datasheet del
propio microcontrolador.

En el registro TCCT2B se disponen los bits CS22,CS21 y CS20 (bit 2,1 y 0). Dichos bits son los encargados de
configurar el PRESCALER del timer.
Veamos las combinaciones de CS22 - CS21 - CS20 respectivamente.

 0- 0 - 0 => No Clock
 0- 0 - 1 => No Prescaling  [0.016 ms]
 0- 1 - 0 => Prescaler=8  [0.128 ms]
 0- 1 - 1 => Prescaler=32  [0.512 ms]
 1- 0 - 0  => Prescaler=64  [1.024 ms]
 1- 0 - 1  => Prescaler=128  [2.048 ms]
 1- 1 - 0  => Prescaler=256  [4.096 ms]
 1- 1 - 1  => Prescaler=1024  [16.384 ms]
He preparado un programa, el cual conmuta el Pin 13 de Arduino cada vez que se produce la interrupción de
Overflow. He recogido la salida de dicho pin con un Analizador Lógico. Lo que se observa, es una señal cuadrada, es
decir el pin esta conmutando de estado ALTO="1" a estado BAJO="0" según la configuración de los bits CS22-CS21-
CS20.

(click para agrandar)

Para lograr el máximo rendimiento del código, he usado control directo de los registros del microcontrolador para
conmutar el pin 13 y así no meter "retrasos" debido a la ejecución de código. Para entendernos, la
instrucción digitalWrite es "lenta".
Los tres registros internos usados por el microcontrolador para el control de los puertos son:

 DDRx   => Configura los pines del puerto como entrada ("0") o salida ("1").
 PORTx => Controla si el estado ALTO y BAJO de los pines de dicho puerto.
 PINx    => Estado de los pines.

siendo x alguno de los tres puertos disponibles en el micro: B,C ó D.


Para saber la equivalencia entre los pines de Arduino con los del micro,
visitar: http://www.arduino.cc/en/Reference/PortManipulation
Cómo se puede ver, el pin 13 de Arduino equivale al PB5 (puerto B, bit 5).

Truco => Si escribes sobre el registro PINx cuando esta declarado cómo salida, el pin conmutará.

_BV() usado en el código es un macro definido en avr/sfr_defs.h, el cual se añade indirectamente al


incluir avr/io.h.  Para hacerlo fácil, lo puedes usar sin añadir dichos includes, ya que esta incluido en el core de
Arduino.
Dicho macro esta definido como: #define _BV( bit ) ( 1<<(bit) )
Lo que hace es poner a "1" el bit definido dentro del paréntesis de la función.

No he usado dicho macro para la configuración de los registros del Timer 2 dentro del setup() para intentar ser
más claro y entenderlo mejor mientras se esta leyendo el datasheet del micro.

Queda de ver una cosa.... ¿Cómo configuro las interrupción de overflow del timer 2?
Para "recoger" las interrupciones generadas por el microcontrolador, nuestro código debe disponer de la siguiente
estructura:

#include <avr/interrupt.h>

ISR(TIMER2_OVF_vect)
{
// código a ejecutar cuando se activa la interrupción
}

ISR(int) define la función que se ejecutará cuando se active la interrupción int, en este caso concreto, la
interrupción de overflow del Timer 2 (TIMER2_OV_vect). Existen más interrupciones cómo por ejemplo: INT0_vect,
USART_RX_vect, ...
Para ampliar información, visitar http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html .

Código del sketch:

#include <avr/interrupt.h>

//-----------------------------------------------------
// Rutina de Interrupcion [TIMER2_OVF_vect es la rutina que se ejecuta cuando el Timer2
->Overflow]
// Arduino tiene un cristal de 16 Mhz
// Por lo que tenemos una interrupcion cada => 1/ ((16000000 / PRESCALER) / 256)
ISR(TIMER2_OVF_vect)
{
 PINB |=_BV(PB5);
}

void setup()
{
 DDRB=_BV(PB5);   // Pin 13 Arduino equivale a PB5

 // NORMAL MODE


 TCCR2A = (1<<COM2A1) | (0<<COM2A0) | (0<<COM2B1)| (0<<COM2B0) | (0<<3) | (0<<2) |
(0<<WGM21) | (0<<WGM20);  

 TCCR2B = (0<<FOC2A) | (0<<FOC2B) | (0<<5) | (0<<4) | (0<<WGM22) | (1<<CS22) |


(0<<CS21) | (0<<CS20);
 
 // Activo Timer2 Overflow Interrupt
 TIMSK2 =(0<<7) | (0<<6) | (0<<5) | (0<<4) | (0<<3) | (0<<OCIE2B) | (0<<OCIE2A) |
(1<<TOIE2);  
 
 // Oscilador interno
 ASSR = (0<<7) | (0<<EXCLK) | (0<<AS2) | (0<<TCN2UB) | (0<<OCR2AUB) | (0<<OCR2BUB) |
(0<<TCR2AUB) | (0<<TCR2BUB) ;
 
 //Activo interrupciones globales.
 sei();
}

void loop(){  

Veámos ahora un ejemplo de cómo usar el Timer2 para controlar diferentes tareas. En este ejemplo,
conmutaremos el estado de dos pines (pin 13 y pin 1 de Arduino) a dos frecuencias diferentes. Es decir, haremos
que el led conectado al pin 13 parpadee cada 10 ms y que el pin 1 cada 25 ms.
Para ello configuramos nuestro Timer2 para que active la interrupción cada 1ms. Dentro de la interrupción
aumentará una variable llamada ticks. Dicha variable será la base para controlar la ejecución del resto de mi
programa.
Por lo que el flujo de mi programa vendrá controlado basado en unidades de 1ms (variable ticks). Esto es la base de
cómo hacer "tareas multiples" con un microcontrolador.
(click para agrandar)

Código del sketch 2:

#include <avr/interrupt.h>

//DECLARACION DE VARIABLES GLOBALES


volatile unsigned long ticks;
unsigned long Tarea1;
unsigned long Tarea2;

//-----------------------------------------------------
// Rutina de Interrupcion [TIMER2_OVF_vect es la rutina que se ejecuta cuando el Timer2
->Overflow]
// Arduino tiene un cristal de 16 Mhz
// Por lo que tenemos una interrupcion cada => 1/ ((16000000 / PRESCALER) / 256)
ISR(TIMER2_OVF_vect)
{
ticks++;
}

void setup()
{
DDRB=_BV(PB5); // Pin 13 Arduino equivale a PB5
DDRD=_BV(PD1); // Pin 2 Arduino equivale a PD1

// NORMAL MODE
TCCR2A = (1<<COM2A1) | (0<<COM2A0) | (0<<COM2B1)| (0<<COM2B0) | (0<<3) | (0<<2) |
(0<<WGM21) | (0<<WGM20);

TCCR2B = (0<<FOC2A) | (0<<FOC2B) | (0<<5) | (0<<4) | (0<<WGM22) | (1<<CS22) |


(0<<CS21) | (0<<CS20);
//Configurado a 1.024 ms

// Activo Timer2 Overflow Interrupt


TIMSK2 =(0<<7) | (0<<6) | (0<<5) | (0<<4) | (0<<3) | (0<<OCIE2B) | (0<<OCIE2A) |
(1<<TOIE2);

// Oscilador interno
ASSR = (0<<7) | (0<<EXCLK) | (0<<AS2) | (0<<TCN2UB) | (0<<OCR2AUB) | (0<<OCR2BUB) |
(0<<TCR2AUB) | (0<<TCR2BUB) ;

// Inicializo variables
Tarea1=10;
Tarea2=25;

//Activo interrupciones globales.


sei();
}

void loop() {

if (ticks>=Tarea1)
{
PINB |=_BV(PB5); //Conmuto pin 13
Tarea1+=10; //Configuro para que se ejecute de nuevo la Tarea1 dentro de 10
ticks
}

if (ticks>=Tarea2)
{
PIND |=_BV(PD1); //Conmuto pin 2
Tarea2+=25; //Configuro para que se ejecute de nuevo la Tarea2 dentro de 25
ticks
}

Espero que ésto ayude y no dudes en contactar conmigo si encuentras algun error.

También podría gustarte