Olá!
Estou com algumas dúvidas relacionadas à programação de um frequencímetro utilizando o mega8.
No projeto que utilizarei, vou contar de 0a 220 Hz. Desejo que a frequência seja um número real, não um inteiro (ex: 14.905 Hz).
Acontece que da maneira que escrevi o código, conforme a frequência aumenta aparece um erro, tipo, se coloco 1KHz na entrada ele conta
1041.07 Hz. Se coloco 100 Hz ele conta 100.81 Hz.
o mínimo que ele conta é 0.25 Hz. o máximo está em torno de 2 KHz.
Segue o código, gerado no Codevision:
#include <mega8.h>
#include <stdio.h>
#include <lcd.h>
// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x12 ;PORTD
#endasm
/*----------------------Rotina de detecção da frequência---------------------------------*/
float pulso;
float T,f;
// Timer 1 input capture interrupt service routine
interrupt [TIM1_CAPT] void timer1_capt_isr(void)
{
pulso=TCNT1;
TCNT1=0;
T=pulso*0.000064; // T é o período e 0.000064 é o tempo gasto em cada incremento de TCNT1 1/( Tosc= 4Mhz/Prescaler=256)
f=1/T;
}
/*---------------------------------Fim da rotina-------------------------------------*/
char* lcd_buf[20];
void main(void)
{
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 15,625 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Rising Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: On
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x44;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x20;
// Global enable interrupts
#asm("sei")
// LCD module initialization
lcd_init(16);
while (1)
{
lcd_gotoxy(0,0);
sprintf(lcd_buf,"FREQ: %5.2f Hz",f); //exibe a frequência no LCD
lcd_puts(lcd_buf);
}
}
Essa é a melhor maneira de se construir um frequencímetro?
O que posso otimizar no código? O que estou fazendo de errado?
O projeto que fiz só que utilizando interrupções externas e o timer 0 gerando interrupcoes a cada 1 segundo funciona sem dar erros, mas o valor medido é sempre um inteiro.
Link para o programa com simulação no Proteus.
http://www.4shared.com/file/49642226/11 ... d=1b1a6207
Obrigado!
Abraços!!