PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Frequenzmessen mit Timer0 klappt nicht.



starkstrom90
12.07.2011, 16:43
Hallo,
ich bin hier mit einem Kollegen seit Stunden am überlegen wieso unser
kleiner Frequenzmesser nicht das anzeigt was er soll.

Wir wollen 100Hz messen, haben dafür ein AtMega168 mit internen 8MHz
genommen, der per Timer0 die Zeit messen soll.

Wir prüfen das Signal einfach in der Main-Schleifen, wollten kein
INT0-Interrupt, sollte eig. auch so gehen.

Mit einem Prescaler von 1024 kommen wir dann auf 7812,5Hz, mit der sich
der TCNT0 um eins erhöht. Ein Overflow sollte es nicht geben, da erst ab
einer gemessenen Frequenz von ca 30Hz der TCNT0 bei 256 ist.

Jetzt sollte uns unser LCD irgendwas um die 70 ausgeben (1/100Hz /
1/7812.5Hz = 78,125)

Nur unser Display zeigt jetzt dauerhaft "24" an. Das können wir uns
nicht erklären. Jemand eine Idee?

MfG


#include <avr/io.h>
#include "lcd.h"
#include <avr/delay.h>
#include <avr/interrupt.h>

void convRPM(int intRPM)
{
int first = intRPM/10000;
lcd_data(first + 48);
//lcd_setcursor(1,2);
int second = (intRPM - (first*10000)) / 1000;
lcd_data(second + 48);
int third = (intRPM - (first*10000) - (second*1000)) / 100;
lcd_data(third + 48);
int fourth = (intRPM - (first*10000) - (second*1000) - (third*100)) / 10;
lcd_data(fourth + 48);
int fifth = (intRPM - (first*10000) - (second*1000) - (third*100) - (fourth*10)) / 1;
lcd_data(fifth + 48);
}

int main(void)
{

lcd_init();
int up = 0;
// Timer 0 konfigurieren
TCCR0B |= _BV(CS02) | _BV(CS00); //Prescaler 1024 -> bei 8 MHz -> 7812,5Hz
// Overflow Interrupt erlauben
TIMSK0 |= _BV(TOIE0); //Bei 256 und 7812,5Hz -> 30,5 Hz
// Global Interrupts aktivieren
sei();
lcd_setcursor( 0, 1 );
DDRC = 0x00;
PORTC = 0x00;
lcd_string("RPM");

while(1)
{
if (!(PINC & (1 << 5))) // Taster gedrückt
{
if( up == 0) //steigende Flanke
{
up = 1;
//content
lcd_setcursor(0,2);
convRPM(TCNT0);
TCNT0 = 0;
}
}else{ //fallende Flanke
up = 0;
}
}

return 0;
}

ISR (TIMER0_OVF_vect)
{
lcd_setcursor( 0, 1 );
lcd_string("--- OVERFLOW");
}

radbruch
12.07.2011, 17:02
So vielleicht?

temp = TCNT0;
TCNT0 = 0;
up = 1;
//content
lcd_setcursor(0,2);
convRPM(temp);

oder so:

...
lcd_string("RPM");

while((PINC & (1 << 5))) // warten falls Signal high ist
while(1)
{
while(!(PINC & (1 << 5))) // warten solange Signal low ist
TCNT0 = 0; // Timer zurücksetzen
while(PINC & (1 << 5)) // warten solange Signal high ist
int temp = TCNT0; // Timerstand merken...
lcd_setcursor(0,2); // ... und ausgeben
convRPM(temp);
}
return 0;
}

starkstrom90
12.07.2011, 17:13
Ah, natürlich. Meine LCD-Routine "frisst" die Hälfte der Zeit.

Danke vielmals