O código fonte:
//************************************************************************ // usando o modo captura de pulsos para ler frequencia(range 1 a 100KHZ) // Version : 1.2 // microcontrolador : AVR ATMega328 // Autor : Aguivone // descrição : captura de eventos externos // data : 11/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; long filtro; long leitura[6]; int ler=0; //////////////////////////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; filtro = 1; } else { lido = estouro + ICR1; if(lido >35000)// em testes de bancada vi que abaixo desse valor o avr fica impreciso { flag_inte++; if(ler < 6) {//enquanto menor que 6 pega leitura // em 1 segundo temos 15999693 ciclos ao inves de 16000000(segundo simulação do proteus) //logo para calcular a frequencia basta: lido = 15999693 / lido; if(filtro > 1) { lido = lido * filtro ; } leitura[ler] = lido; flag_inte = 0; ler++; } } else { filtro++; } } } ///////////////////////////////////////////////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 long filtro_de_ruido(int val) { long valor; //comparação de 3 valores pelo menos 2 leituras devem ser iguais if((leitura[val] == leitura[val+1])||(leitura[val] == leitura[val+2])) {//ok valor = leitura[val]; } else { if(leitura[val+1] == leitura[val+2]) {//ok valor = leitura[val+1]; } } return(valor); } //////////////////////////////////////////////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); ler = 0; for(;;) { if(ler >= 6 ) { cli(); long compara1,compara2; compara1 = filtro_de_ruido(0); compara2 = filtro_de_ruido(3); //se de 6 amostras pelo menos 4 forem iguais if((compara1 == compara2)&&(compara1 > 0))//filtra leitura errada { impri_serial("-> "); int_to_char(compara1);//isso garante melhor performace impri_serial("\n\r"); } flag_inte = 0; ler=0; _delay_ms(100); sei(); } }//laço for }//main
Atenção desabilite as optimizações do compilador para funcionar.
ResponderExcluir