vďaka,
ako mám vo zvyku, prikladám hotovú vec. Je určený pre meranie frekvencie do 200Hz, ale prerobiť to na vyššie frekvencie je jednoduché, stačí prerobiť počet miest na displeji a:
Hodnota sa obnovuje každú polsekundu, s tým že sa ukladá aj predchádzajúca polsekunda, takže je vyhodnocovanie frekvencie každú sekundu. Pre meranie vyšších frekvencii , a rýchlo meniacich sa frekvencii treba určite skrátiť čas merania, podľa meranej frekvencie a požadovanej presnosti.
edit: a ešte by miesto interného oscilátoru zlepšil presnosť externý kryštál, ale to naozaj nepotrebujem, už táto presnosť ktorú dosahujem je viac ako postačujúca
Kód: Vybrat vše
#define F_CPU 4000000UL // 4 MHZ rychlost uPC
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "lcd.h"
signed int pocet_otacok;
signed int pocet_otacok2;
signed int otacky;
signed int otackyC;
signed int otackyD;
signed char ii;
void nast_komp(void)
{
DIDR |= _BV(AIN1D)| _BV(AIN0D); //vypnutie digital input
/*nastavenie vnutornej referencie komparatoru, umoznenie prerusenia*/
ACSR |= _BV(ACBG)| _BV(ACIE)| _BV(ACIE);
}
void casovac1(void)
{
TCCR1A |= _BV(WGM11)| _BV(WGM10); // WGM = phase correct, update of OCR1A on top, top=OCR1A
TCCR1B |= _BV(CS12)| _BV(CS10)| _BV(WGM13); // CS1X = 1024 prescaller
TIMSK |= _BV(TOIE1); // umoznenie prerusenia
OCR1A=1007; // top phase correct PWM, f = 4000000/(2*976*1024)= 2 Hz
//ale kvoly doladeniu presnosti empiricky zistená hodnota 1007
}
void main()
{
sei(); // Enable Global Interrupts
casovac1();
nast_komp();
InitLCD(LS_NONE); //inicializacia LCD
LCDClear(); // clear
for(;;) // Loop Forever
{
if(otacky>=1) // z dovodu pekneho cisla na displeji
{ii=1;} // miesto "010.5" to cele ukazuje
if(otacky>=10) // "10.5" atď
{ii=1;} //
if(otacky>=100)
{ii=2;}
if(otacky>=1000)
{ii=3;}
LCDWriteStringXY(0,0,"otacky:"); // horny riadok 2*16 lcd displej
LCDWriteStringXY(5,1,"."); // spodny riadok 2*16 lcd displej, desatinna ciarka
LCDWriteStringXY(10,1,"o/s"); // spodny riadok 2*16 lcd displej
otackyC=otacky/10; // cast otacok pred desatinnou ciarkou
otackyD=otacky%10; // zvysok po deleni, za desatinnou ciarkou(0,5)
LCDWriteIntXY(5-ii,1,otackyC,ii); // spodny riadok 2*16 lcd displej
LCDWriteIntXY(6,1,otackyD,1); // spodny riadok 2*16 lcd displej
_delay_ms(500);
//_delay_ms(500);
LCDClear(); // clear
}
}
ISR(ANA_COMP_vect) // prerusenie od analogoveho komparatoru
{
pocet_otacok=(pocet_otacok+1);
_delay_ms(1); // delay
ACSR |=(1<<ACI); // zrusenie priznakoveho bitu
}
// otacky za sekundu
ISR(TIMER1_OVF_vect)
{
otacky=(pocet_otacok+pocet_otacok2)*5;
// suma aktualnych a predch. otacok *5(z dovodu desatinnej ciarky)
pocet_otacok2=pocet_otacok; // ulozenie aktuálnych otáčok do otáčok predchádzajucich
pocet_otacok=0; // vynulovanie poctu otacok, aby nastalo pripocitavanie odznova
TIFR |=(1<<TOV1); // zrusenie priznakoveho bitu
}
edit: editovaný popis na úvod + nastavenie príznakového bitu