Manejo de Temporizadores AVR Parte 2

5

Click here to load reader

Transcript of Manejo de Temporizadores AVR Parte 2

Page 1: Manejo de Temporizadores AVR Parte 2

PROGRAMACIÓN DEL TEMPORIZADOR COMO CONTADOR DE EVENTOS En la sección anterior, hemos utilizado los temporizadores del AVR para generar

retardos de tiempo. El temporizador del AVR también puede ser usado para contar,

detectar y medir el tiempo de los acontecimientos que suceden fuera del AVR

Cuando el temporizador se utiliza como un contador de tiempo, la frecuencia del

cristal del AVR se usa como fuente de reloj. Cuando se utiliza como un contador, sin

embargo, se trata de una salida de impulsos del lado del AVR que incrementa el

registro TCNTx. Observe que, en el modo de contador, los registros TCCR, OCR0, y

TCNT son los mismos que para el temporizador discutido en la sección anterior.

Los bits CS00, CS01, and CS02 en el registr0 TCCR0 Recuerde que en la sección anterior que los bits de CS (clock selector) en el registro

TCCR0 sirven para seleccionar la fuente de para el temporizador. If CS02:CS00 está

entre 1 y 5, el temporizador recibe impulsos del oscilador de cristal. En contraste,

cuando CS02:CS00 es 6 o 7, el temporizador se utiliza como un contador de impulsos y

obtiene los pulsos desde una fuente externa al chip AVR. Vea la Figura.

Por lo tanto, cuando CS02:CS00 es 6 o 7, el registro contador TCNT0 incrementa su

cuenta cuando los pulsos se alimentan por el pin T0 (entrada externa del reloj del

Timer / Contador 0).

Ejemplo

Encuentra el valor de TCCR0 si queremos programar Timer 0 como contador en modo

Normal. Utiliza un reloj externo para la fuente de reloj y el incremento es con el flanco

positivo.

Solución:

TCCR0 = 0000 0111 Normal; fuente de reloj externa, no prescaler

T0 es un pin de función alternativa de PORTB bit 0.En el caso del Timer 0, cuando

CS02:CS00 es 6 o 7, el pin T0 proporciona el pulso de reloj y el contador cuenta hacia

Page 2: Manejo de Temporizadores AVR Parte 2

arriba después de cada pulso de reloj procedente de pin, para el Timer 1, cuando CS12:

10 es 6 o 7, el pulso de reloj viene por el pin T1 (entrada de reloj externa del Timer /

Contador 1) hace que el contador TCNT1 incremente. Cuando CS12:CS10 es 6, el

contador cuenta hacia arriba en el flanco negativo. Cuando CS12:CS10 es 7, el

contador cuenta hacia arriba en el flanco positivo. T1 es un pin de función alternativa

de PORTB bit 1.

Ejemplo

Suponiendo que un pulso de reloj de 1 Hz se alimenta en el pin T0 (PD4), escriba un

programa para que Contador 0 cuente en el modo normal contando los pulsos en el

flanco descendente y mostrar el estado de la cuenta TCNT0 en PORTC.

#include <avr\io.h>

int main () {

PORTD|=(1<<PD4); //Pullup activada

DDRC = 0xFF; //PORTC como salida

TCCR0 = 0x6; //Timer 0, contador, flanco bajada

while (1) {

PORTC = TCNT0;

if((TIFR&(1<<TOV0))==1)//desbordamiento

TIFR |=(1<<TOV0); //Borra el indicador

}//repite por siempre

}

En el Ejemplo de arriba, estamos utilizando Timer 0 como un contador de eventos que

cuenta los pulsos de reloj que se alimentan en PD4. Estos pulsos de reloj podría

representar el número de personas que pasan a través de una entrada, o de rotaciones

de una rueda, o cualquier otro evento que se puede convertir en pulsos.

Los datos de TCNT0 se muestran en binario.

Antes de terminar esta sección, es necesario establecer un punto importante. Se

podría pensar que monitorear las banderas TOV y OCR el microcontrolador pierde

tiempo. Eso es cierto pero hay una solución para esto: el uso de las interrupciones.

Usando interrupciones nos permite hacer otras tareas con el microcontrolador.

Ejemplo

Supongamos que un reloj externo de 1hz se alimenta en el pin T1 (PD5). Escriba un

programa en C para que el contador 1 con flanco ascendente se incremente para

contar los pulsos y mostrar los registros TCNT1H y TCNT1L en PORTB y PORTC,

respectivamente.

Page 3: Manejo de Temporizadores AVR Parte 2

Solución:

#include "avr/io.h"

int main () {

PORTD |= (1<<PD5); //activa pull-up de PD5 = T1

DDRC = 0xFF; //PORTC salida

DDRB = 0xFF; //PORTB salida

TCCR1A = 0x00; //Fuente de reloj configurada

TCCR1B = 0x06; //como contador con flanco desendente

TCNT1H = 0x00; //Inicia en cero

TCNT1L = 0x00; //Inicia en cero

while (1) {

do {

PORTC = TCNT1L;

PORTB = TCNT1H; //escribe el valor en los puertos

}while ((TIFR&(1<<TOV1))==0);//espera desbordamiento

TIFR |=(1<<TOV1); //Borra el indicador

}

}

PROGRAMACIÓN DE INTERRUPCIONES DEL TEMPORIZADOR

Desbordamiento del temporizador y bandera de interrupción La bandera de desbordamiento del temporizador se pone a uno cuando el

temporizador se desborda, vimos cómo monitorear la bandera del temporizador. En el

monitoreo de TOV0, tenemos que esperar hasta TOV0 sea uno. El problema con este

método es que el microcontrolador tiene que esperar hasta que TOV0 se coloque a

uno, y no se puede hacer nada más. Usando las interrupciones evitamos atar al

microcontrolador en este tiempo. Si la interrupción del temporizador está habilitada

en el registro de interrupción, TOV0 se pone a uno cada vez que el temporizador se

desborda y el microcontrolador salta a la tabla de vectores de interrupción para dar

servicio a la ISR. De esta manera, el microcontrolador puede hacer otras cosas hasta

que sea notificado de que el temporizador se ha desbordado. Para utilizar una

interrupción en lugar de un monitoreo constante de TOV, primero debemos activar la

interrupción porque todas las interrupciones están enmascaradas en el reset. El bit

TOIEx permite la interrupción para un temporizador determinado. Los bits TOIEx están

en el registro TIMSK como se muestra en la Tabla.

Bits bandera de interrupción de temporizador y registros asociados

Interrupción Bandera Registro Bit Habilitación Registro Timer 0 TOV0 TIFR TOIE0 TIMSK Timer 1 TOV1 TIFR TOlE1 TIMSK Timer 2 TOV2 TIFR TOIE2 TIMSK

Page 4: Manejo de Temporizadores AVR Parte 2

Ejemplo

Uso del Timer 0 para generar una onda cuadrada en el pin PORTB bit 1, mientras que al

mismo tiempo transfiere datos del PORTC a PORTD.

#include "avr/io.h"

#include "avr/interrupt.h"

int main (){

DDRB |= 0x02;//DDRB 1 = output

TCNT0= -32; //valor del timer para 4uS

TCCR0 =0x01; //Normal mode, int clk, no prescaler

TIMSK=(1<<TOIE0) ; //enable TimerO overflow interrupt

sei (); //enable interrupts

DDRC= 0x00; //make PORTC input

DDRD=0xFF; //make PORTD output

while (1) PORTD=PINC; //wait here

}

ISR(TIMER0_OVF_vect) { //ISR for TimerO overflow

TCNT0 = -32;

PORTB ^= 0x2;

}

Ejemplo

Usando las interrupciones Timer 0 y Timer 1 y cristal de 8Mhz, escriba un programa en

el que:

(a) PORTC se incrementa cada vez que el Timer 1 se desborda una vez por segundo.

(b) Un pulso se alimenta al Timer 0 y se usa como contador. Cada vez que el contador

llegue a 200 se cambiará el estado del pin PORTB bit 4.

Solución:

Para preescalar = 256 tenemos TClock= (1/ 8 MHz) x 256 = 32 uS y 1 s/32 us = 31250. De

manera que TCNT1 = 31250 = 0x7A12

#include "avr/io.h"

#include "avr/interrupt.h"

int main (){

DDRB |= 0x10;//DDRB 4 = salida

PORTB |= 0x10;// activa pullup

TCNT0= -200; //carga el TimerO con -200

TCNT1H=(-31250) >>8; //byte alto para Timer 1

TCNT1L = (-31250)&0xFF;//se desborda despues de 31250 pulsos

TCCR1A= 0x00; //modo Normal

TCCR1B= 0x04; //,reloj interno, prescaler 1:256

TCCR0 =0x06; //Modo Normal , flanco descendente, no prescaler

TIMSK=(1<<TOIE0)|(1<<TOIE1) ; //habilta las interrupciones del TimerO y del

Timer 1

sei (); //habilita todas las interrupciones

Page 5: Manejo de Temporizadores AVR Parte 2

PORTD|=(1<<PD2); //Pullup activada

DDRC=0xFF; // PORTC como salida

while (1) ; //wait here

}

ISR(SIG_OVERFLOW0) { //ISR para TimerO

TCNT0 = -200;

PORTB ^= 0x10;

}

ISR (SIG_OVERFLOW1) {//ISR para Timer1

TCNT1H=(-31250) >>8; //byte alto para Timer 1

TCNT1L = (-31250)&0xFF;//se desborda despues de 31250 pulsos

PORTC ++; //incrementa PORTC

}