sexta-feira, 1 de março de 2013

Frequêncimetro com atmega328 - usando ICP1

Veja na simulção como funcionou bem na faixa que vai de 1 hz a 10 Khz(acima deste valor até lê mas fica impreciso) , para conseguir ler sinal de frequencia mais alta é preciso usar um divisor de frequência ou implementar funçoes para isto.O compilador usado é o avr studio.



O Código fonte :

//************************************************************************
//            usando o modo captura de pulsos para ler frequencia(range 1 a 10KHZ)
//  Version    : 1.2
//  microcontrolador : AVR ATMega328
//  Autor        : Aguivone
//  descrição  : captura de eventos externos  
//  data : 01/03/2013.
//
//************************************************************************
#define F_CPU 16000000UL  //  deve vir antes das interrupçoes
#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>
#include <util/delay.h>
#include <string.h>

/////////////////////////declaração da variaveis ///////////////////////////////////
int flag_inte=0;
long estouro = 0,lido_estouro=0;
long lido;

//////////////////////////interrupções do timer1 ///////////////////////////////////
#define liga_pino(x,y) x |= _BV(y)
#define desliga_pino(x,y) x &= ~(_BV(y))
#define alterna_pino(x,y) x ^= _BV(y)


ISR(TIMER1_OVF_vect )
  {                    //interrupção overflow
       estouro= estouro + 65535;
  }  
ISR(TIMER1_CAPT_vect)
{              //interrupção de captura de eventos externos.
          if(flag_inte < 2)
          {
          flag_inte++;
          TCNT1 = 0;//zera timer 
          TIFR1 = 0XF0; //limpa interrupcão pendente
          estouro = 0 ;
          lido = 0;
          }
          else
          {
              lido = estouro + ICR1;
              flag_inte++;                             
          }           
          
}
///////////////////////////////////////////////funçoes usadas pela usart////////////////////////////////////////////////

void RS232_inicializa(unsigned int BAUD)
{
   unsigned int velocidade = F_CPU/16/BAUD-1;
   // veja que na simulação do proteus dá erros nas velocidade diferentes de 9600 mas na pratica funciona.
    UCSR0A = 0X20;
    UBRR0H = (unsigned char)(velocidade>>8);
    UBRR0L = (unsigned char)velocidade;
    UCSR0B = 0X18;//não vou habilitar nenhuma interrupção da porta serial
    /* 8 bits , 1 stop bit, assincrono , sem paridade,modo nornal */
    UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}

void escreve_caracter(unsigned char carac)
{  
            _delay_loop_1(1);//tempo para estabilizar tensão            
            while ( !( UCSR0A & (1<<UDRE0)) ); //espera transmitir para enviar um novo
            UDR0 = carac;    
            while ( !( UCSR0A & (1<<UDRE0)) ); //espera transmitir desabilita a transmissão
            _delay_loop_1(1);//tempo para garantir o envio
}
void impri_serial(const char frase[20])
{
      unsigned int indice=0;
      unsigned int tamanho = strlen(frase);    
       while(indice<=tamanho)///veja que o programa pode travar se aqui não tiver as duas aspas
       {
            escreve_caracter(frase[indice]);
            indice++;
       }
}

void int_to_char(long quant)
{

       char convert_char5='0';
       char convert_char6='0';
       char convert_char7='0';
       char  convert_char8='0';
       char convert_char9='0';

      
       while(quant>=10000)
        {
           quant=quant-10000;
         convert_char5++;
         }

       while(quant>=1000)
        {
         quant=quant-1000;
         convert_char6++;
         }
       while(quant>=100)
        {
         quant=quant-100;
         convert_char7++;
         }
       while(quant>=10)
        {
         quant=quant-10;
        convert_char8++;
         }
       while(quant>=1)
        {
           quant=quant-1;
         convert_char9++;
         }
          escreve_caracter(convert_char5);
          escreve_caracter(convert_char6);
          escreve_caracter(convert_char7);
          escreve_caracter(convert_char8);
          escreve_caracter(convert_char9);

} 

  
/////////////////////////////////////////////////Funções usadas/////////////////////////////////////////////

void inicializa_modo_captura(void)
{
   TCCR1A = 0X00;//não tem uso para o modo captura de eventos externos
   TCCR1B = 0x01;//filtro desabilitado de ruido habilitado,captura na borda de descida do sinal, clock interno/1
   TCCR1C = 0X00;//não tem uso para o modo captura de eventos externos
   TIMSK1 = 0x21; //habilita interrupção de estouro de timer e de captura

}

//opcional vai depender da aplicação



//////////////////////////////////////////////função principal///////////////////////////////////////////
int main(void)
{
            DDRD = 0X1E;
            DDRB = 0x00;  //inicializa portb como  entrada
            PORTB = 0XFF;//desabilita pull-ups
            DDRC = 0xFF;  //inicializa portC como saida
            PORTC = 0;//limpa as portas logicas.
            inicializa_modo_captura();
            RS232_inicializa(9600);
            impri_serial("Inicializado...\n\r");
            sei(); // habilita interrupções
            desliga_pino(PORTC,0);
            desliga_pino(PORTC,1);
           for(;;)
            {
              if(flag_inte == 3)
               {
                  cli();
                  impri_serial("-> ");
                 // em 1 segundo temos 15999693 ciclos ao inves de 16000000(segundo simulação do proteus)
                  //logo para calcular a frequencia basta:
                  lido = 15999693 / lido;
                  int_to_char(lido);//isso garante melhor performace
                  impri_serial("\n\r");
                  flag_inte = 0;
                  _delay_ms(1000);                  
                  sei(); 
               }
          
            }//laço for
}//main

Um comentário :

  1. Bom dia. Compilei no AtmelStudio e não funcionou na simulação com o Proteus.

    ResponderExcluir

olá,digite aqui seu comentário!