Forum: Mikrocontroller und Digitale Elektronik Frequenzmessung mit ATMega16


von Karlheinz Druschel (Gast)


Angehängte Dateien:

Lesenswert?

Hi Leuts,

folgendes:
Ich habe hier einen ATMega16 auf dem STK500 und zwei externe Signale, A
und B. Diese Signale können 3 Zustände haben: 0V, 5V oder
Rechteckimpulse mit ca. 4 Hz. Ich muss alle drei Zustände auswerten.
Nun dachte ich, ich könnte mir mit externen Interrupts helfen, deshalb
habe ich die Signale auf INT0 und INT1 verdrahtet.
Variante 1: Für eine bestimmte Zeit (beispielsweise 600 ms) zähle ich
die Flankenwechsel
Variante 2: Ich zähle die Zeit zwischen den Flankenwechseln.
Nun gehts aber schon generell beim Timing los: Ich habe mir also eine
Timer-Overflow-Routine geschrieben, die alle 5 ms aufgerufen wird. Zur
Kontrolle toggel ich bei jedem Aufruf PORTA.0. Lt. Oszi klappt das,
auch wenn die Werte für TCNT0 nicht nachberechnen kann.
Nun möchte ich für rund 600 ms messen, bei einem Aufruf alle 5 ms muss
ich also nur bis 120 zaehlen, dann sind 600 ms um. Stimmt aber nicht,
das Signal verschleift irgendwie total. D.h. wenn ich bei einem
Zählerstand von 120 ein Pin toggle, dann sind die 1 und 0 Zeiten
unterschiedlich lang, und einen Zusammenhang mit 120 kann ich nirgendwo
entdecken. Also habe ich wohl ein grundlegendes Problem mit den Timern.
Oder ?

Greets
Karlheinz

von Rahul (Gast)


Lesenswert?

Ist das Signal mit 4Hz frequenzstabil oder variiert die auch noch?
Ohne einen Blick auf deinen Quellcode würde ich folgendes
vorschlagen:
Bei jedem externen Interrupt einen Timer so zurücksetzen, dass er nach
125-150ms (eine Periodenhälfte) überläuft.
Bei konstantem Pegel auf der Leitung kommt es zum Überlauf.
In der INT0-ISR würde ich eine LED setzen, die den Flankenwechsel
anzeigt.
In der Timer-Überlauf-ISR würde ich diese LED dann löschen, und dafür
pegel-abhängig eine andere setzen. Insgesamt also 3 LEDs...

Bei mehr als einem Interrupt könnte man einen Timer verwenden, der
regelmässig (100µs oder so) ein Interrupt auslöst. In dessen ISR werden
dann für jeden Interrupt Variablen heruntergezählt, und bei 0 ein
Überlauf detektiert...

Auf dein Problem mit den Timer bin ich jetzt nicht eingegangen...
Hab die Fragestellung / das Problem wohl auch nicht ganz verstanden.

von johnny.m (Gast)


Lesenswert?

Hallo,

Das cli() und sei() in der ISR kannste Dir sparen, das passiert
automatisch!

Abgesehen davon hast Du den INT0 als Low-Level-sensitiv initialisiert.
Du  inkrementierst Dein nCounterA (wie ist das überhaupt
initialisiert??) ständig mit hoher Rate, so lange das TFlagA gesetzt
ist. Da kann dann kein sinnvoller Wert drinstehen!

Gruß

Johnny

von Karlheinz Druschel (Gast)


Lesenswert?

Stimmt,
jetzt klapperts.
1000 Dank

Greets
Karlheinz

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.