Forum: Compiler & IDEs Gleichzeitiges Nutzen von Input Capture und Compare Unit


von Tommy (Gast)


Angehängte Dateien:

Lesenswert?

Folgendes Szenario stellt sich mir (momentaan in den Weg):
Ich habe ein Rechtecksignal, dessen Frequenz ich mit Hilfe des Input
Capture Unit des Timers 1 meines ATmega32 messen will. Soweit so gut,
das funktioniert auch. Mit dieser Gemessenen Frequenz möchte ich jetzt
eine Sinusschwingung mit PWM und Timer0 erzeugen. Dazu hab ich eine
Tabelle im Flash abgelegt, welche 64 Werte eine viertel Sinusschwingung
enthält. Um nun de aus den 64 Werten resultierenden 128 Schritte für
eine komplette Periode zu durchlaufen lade ich in das OCR1A Register
den gemessenen Frequenzwert, den ich zuvor 7 mal nach rechts verschoben
habe (also durch 128 dividiert - wenn ich jetzt nicht ganz auf dem
Schlauch stehe). Und da fangen die Probleme an. Timer1 läuft im
"normal mode". die Interrupts für Input Capture und
Output_Compare_1_A sind aktiviert und die ISRs sind vorhanden. Die
Frequenzmessung allein funktioniert.
Nun setze ich alles unter Strom und folgendes passiert: Solange das
Rechtecksignal anliegt, erzeugt mir der Timer 0 entweder eine beliebige
Gleichspannung, oder eine Frequenz von 0,8 Hz, aber feiner Sinus.
Schalte ich jetzt mein Rechtecksignal ab, so erzeugt er mir genau die
Frequenz, die ich an den Eingang als Rechteck angelegt habe als schöne
Sinuswelle.
Ich habe schon versucht, den Timer1 anzuhalten, als ich das OCR1A
Register verändert habe (mehr eine Verzweiflungstat), habe OCR1B mit
einbezogen, also beie Interrupts abwechseln ausgeführt und in der ISR
des einen den OCR1x - Registerwert des anderen neu geschrieben. Bei der
Frequenz handelt es sich um eine niedrige Frequenz von < 1kHz, also mein
AVR sollte mit 16 MHz da locker mitkommen. Bei Timer 1 ist ein Prescaler
von fclk/8 eingestellt. das reicht damit für einen Frequenzbereich von
30Hz bis 2MHz (theoretisch). Der dennoch relative kleine Prescaler ist
auf eine möglichst hohe Auflösung der Frequenzmessung zurückzuführen,
auch wenn ich diese im Moment nicht nutzen kann (Timer0).

Der Sourcecode ist als anhang mit bei...

von Peter D. (peda)


Lesenswert?

SIGNAL(SIG_INPUT_CAPTURE1)
...
TCNT1 = 0x0000;
...

Dann kann ja der compareinterrupt nicht gehen.


Peter

von Tommy (Gast)


Lesenswert?

Hallo Peter,
danke für die Antwort, nur versteh ich's nicht ganz. Kannst du mir das
genauer erkären? TCNT1 ist doch das Zählregister des Timer1, oder? Das
will ich bei einem Capture-Ereignis zurücksetzen, so dass der Timer
wieder von vorn beginnt. Und die Compare-Ereignisse sollten ja so ca.
128 mal dazwischen auftreten, da keine schnellen Frequenzändeerungen zu
erwarten sind. Wo liegt mein Denkfehler???

THX

von Peter D. (peda)


Lesenswert?

Laß doch den Timer durchlaufen und nimm dann die Differenz zum
vorherigen Capturewert.


Peter

von Jörg Wunsch (Gast)


Lesenswert?

Wenn Du den alten und den neuen capture-Wert in einer uint16_t
Variablen speicherst und Dir sicher bist, daß zwischen beiden
Ereignissen nicht mehr als ein Überlauf des Zählers erfolgt ist,
kannst Du beide ohne Behandlung eines möglichen Überlaufs direkt
subtrahieren.

von Tommy (Gast)


Lesenswert?

Guten Morgen!
Ich hab jetzt meinen Fehler gefunden.
Hab in der ISR für das Capture-Ereignis das Compareregister nicht
geladen. Da muß natürlich der erste Wert der gemessenen Zeit/128 drin
stehen, sonst steht's bei 0x0000 und da passiert logisch nicht viel &
das Nachladen des Registers bleibt da auch aus.
Trotzdem danke an alle für eure schnelle Hilfe!

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.