sábado, 1 de marzo de 2014

LECTOR DE FRECUENCIA CON COMPARADOR ANALÓGICO Y TIMER1

                   El programa realizado a continuación al igual que el realizado donde se controlaba la interrupción del comparador analógico, presentara una forma sencilla del uso del comparador diferenciándose en el uso del TIMER1 como parte del programa para en este caso en particular realizar la presentación de la frecuencia de la señal colocada en el pin AIN1 con ayuda de la interrupción Timer/Counter1 capture event y una librería para displays de 7 segmentos con la cual se presentaran los resultados. 

DESCRIPCIÓN:

COMPARADOR ANALÓGICO:

                             Como se menciono anteriormente el programa depende del uso del comparador analógico el cual esta configurado para utilizar el pin AIN1 como entrada negativa, ademas la reacción del selector de interrupción  se configuro en el modo de flanco de subida, así como se habilito el bit de ACIC del registro ACSR, el cual permite trigger el TIMER/COUNTER1 para determinar la frecuencia de la señal que se esta analizando. Esto se realiza dentro de la función COMPARADOR() donde ademas se habilita la interrupción global      

TEMPORIZADOR:                 

                                       La configuración del TIMER1 es relativamente sencilla, se configura el modo de funcionamiento que tendrá con ayuda de los bits WGM13..10 del registro TCCR1B,  para este caso se utilizo el modo NORMAL. Enseguida se habilita el inhibidor de ruido de entrada de captura mediante el bit ICNC1 del registro TCCR1B  y se habilita el bit ICES1 del mismo registro, este bit configura el modo de activacion de la entrada de captura del TIMER1, en este caso es en flanco de subida. A continuación se configura el preescalador en 64 para la resolución del temporizador, se inicializa el registro TCNT1 en cero y se habilita la interrupción por entrada de captura.
                                         Tome en cuenta que el preescalamiento utilizado en este programa puede se tomo de forma arbitraria para la demostración del funcionamiento del programa puede utilizarse cualquier otro para el uso del mismo.

INTERRUPCIÓN:

                                        La rutina de interrupción copia el contenido del registro ICR1 en la variable PERIODO la cual es utilizada para determinar la frecuencia de la señal de entrada esto mediante la operación ingresada dentro de la función IF..ELSE donde se restara el valor de la variable PERIODO de PERIODO_ANTERIOR y se guardara en una nueva variable llamada PERIODO_REAL con la cual se determinara la frecuencia. La función IF determina si la variable PERIODO es mayor que PERIODO_ANTERIOR de no ser así realiza la sustracción pero adicionando 65536 tomando en cuenta que se presento un OVERFLOW en el temporizador. Una vez realizada la sustracción se procede a guardar el valor de la variable PERIODO en PERIODO_ANTERIOR para su utilización en la siguiente operación de la rutina de interrupción.

INICIALIZAR DISPLAY:

                              Se inicializan las entradas de los displays de siete segmentos conectados al microcontrolador para esto se utiliza la función initDisplay(); conectándolos en el puerto PORTB los segmentos y en el PORTC los cátodos 

CICLO WHILE(1):

                             Esta función se realiza de forma cíclica, realiza la determinación del valor de la frecuencia de la señal en el pin AIN1 para esto realiza la siguiente operación:

                                frecuencia=125000/((float)PERIODO_REAL);
freq_entero=(int)frecuencia;
                          
                             El valor 125000 se determina dividiendo la frecuencia de reloj con el preescalamiento establecido en la función TEMPORIZADOR(), también puede realizarse de la siguiente forma:   

                        frecuencia=(F_CPU/64)/((float)PERIODO_REAL);
freq_entero=(int)frecuencia;

                                 En seguida se guarda el valor de la frecuencia obtenida en tres variables las cuales representarán las centenas, decenas y unidades respectivamente:

                        f_c=freq_entero/100;
f_d=(freq_entero-100*f_c)/10;
f_u=freq_entero-100*f_c-10*f_d;

DISPLAY:

                                      Para finalizar se mostrara la frecuencia mediante tres displays de siete segmentos para lo cual se procede con las centenas deshabilitando en primer logar los pines conectados a los cátodos de las decenas y unidades, mediante la función salida_7seg(unsigned int value) se presenta el valor de la variable ingresada para presentarse en el display de siete segmentos y para finalizar se setea el pin del cátodo de las centenas; con las decenas y unidades se realiza el mismo proceso mencionado anteriormente.   
NOTA: Alguna duda o sugerencia puede ingresarla en los comentarios para aclararla y mejorar la presentación de los programas o la explicación.

PROGRAMA:

/*
 * triggerCampureTimer.c
 *
 * Created: 01/03/2014 0:49:14
 *  Author: TERRAFORMARS
 */ 


#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 8000000UL // XTAL de 8 MHz
#endif
#include <util/delay.h>
#include <avr/interrupt.h>
#include <util/atomic.h>
#include "7_segmentos.h"

#define setbit(sfr,bit) (_SFR_BYTE(sfr)|=(_BV(bit)))
#define clearbit(sfr,bit) (_SFR_BYTE(sfr)&=~(_BV(bit)))
#define bittoggle(sfr,bit)(_SFR_BYTE(sfr)^=_BV(bit))

unsigned int PERIODO=0,PERIODO_ANTERIOR=0,PERIODO_REAL=0,freq_entero;
unsigned int f_c,f_d,f_u;
volatile float frecuencia;

ISR (TIMER1_CAPT_vect){
//LEER DATO GUARDADO EN ICR1 
PERIODO=ICR1;
if (PERIODO>PERIODO_ANTERIOR)//SI EL VALOR LEIDO ES SUPERIOR AL VALOR PRECEDENTE REALIZAR LA SUSTRACCION DE 
{                            //FORMA NORMAL  
PERIODO_REAL=PERIODO-PERIODO_ANTERIOR;
}
else                         //SI EL VALOR LEIDO ES INFERIOR AL VALOR PRECEDNTE SUMAR 65536 A LA RESTA PARA 
{                            //OBTENER EL NUMERO REAL
PERIODO_REAL=65536+PERIODO-PERIODO_ANTERIOR;
}
//CARGAR EL VALOR LEIDO A LA VARIABLE DE COMPARACION 
PERIODO_ANTERIOR=PERIODO;
}


//CONFIGURAR COMPARADOR ANALOGICO
void COMPARADOR(){
//ENTRADA NEGATIVA AIN1
setbit(ADCSRB,ACME);
setbit(ADCSRA,ADEN);
//MODO DE INTERRUPCION EN FLANCO DE SUBIDA
setbit(ACSR,ACIS1);
setbit(ACSR,ACIS0);
//HABILITAR CAPTURA DE ENTRADA DEL COMPARADOR ANALOGICO
setbit(ACSR,ACIC);
//HABILITAR INTERRUPCION GLOBAL
sei();
}

//CONFIGURACION DE TIMER1
void TEMPORIZADOR(){
//CONFIGURACION DE MODO DE GENERADOR DE FORMA DE ONDA
//MODO NORMAL
clearbit(TCCR1B,WGM13);
clearbit(TCCR1B,WGM12);
clearbit(TCCR1A,WGM11);
clearbit(TCCR1A,WGM10);
//HABILITAR EL CANCELADOR DE RUIDO DE LA ENTRADA DE CAPTURA
setbit(TCCR1B,ICNC1);
//FLANCO DE SUBIDA DE ENTRADA DE CAPTURA 
setbit(TCCR1B,ICES1);
//CONFIGURACION DE PREESCALAMIENTO 64
clearbit(TCCR1B,CS12);
setbit(TCCR1B,CS11);
setbit(TCCR1B,CS10);
//CARGAR REGISTRO TCNT1
TCNT1=0;
//HABILITAR INTERRUPCION POR ENTRADA DE CAPTURA
setbit(TIMSK1,ICIE1);
}

int main(void)
{
initDisplay();
TEMPORIZADOR();
COMPARADOR();
    while(1)
    {
        //TODO:: Please write your application code 
frecuencia=125000/((float)PERIODO_REAL);
freq_entero=(int)frecuencia;
            
f_c=freq_entero/100;
f_d=(freq_entero-100*f_c)/10;
f_u=freq_entero-100*f_c-10*f_d;
//DISPLAY CENTENAS
setbit(Pdisp_3,disp_3);
setbit(Pdisp_2,disp_2);
salida_7seg(f_c);
clearbit(Pdisp_1,disp_1);
       _delay_ms(20);
//DISPLAY DECENAS
   setbit(Pdisp_1,disp_1);
   setbit(Pdisp_3,disp_3);
   salida_7seg(f_d);
clearbit(Pdisp_2,disp_2);
_delay_ms(20);
//DISPLAY UNIDADES
   setbit(Pdisp_2,disp_2);
   setbit(Pdisp_1,disp_1);
salida_7seg(f_u);
clearbit(Pdisp_3,disp_3);
_delay_ms(20);

    }
}

IMÁGENES:

DIAGRAMA DE BLOQUES DEL COMPARADOR ANALÓGICO 


DIAGRAMA DE BLOQUES DEL TIMER/COUNTER 1 DE 16 BITS

SIMULACIÓN DEL PROGRAMA EN ISIS PROTEUS


SIMULACIÓN EN ATMEL STUDIO







LINKS:

https://mega.co.nz/#!RgETBCaI!noxRIezJyxNWX2_nizqjc-GoxGZflSDB1ElIhEpULrU












No hay comentarios:

Publicar un comentario