Hallo, ich habe folgendes Problem: Ich will in einem Unterprogramm mit dem 16Bit Counter T1 des Mega32 ein externes Rechtecksignal variabler Frequenz (ca 2-50kHz) messen. Ich benutze dazu noch den Timer2 zum "Gaten", also gewissermaßen als Zeitbasis. Am Eingang T1 (also an PB1) liegt definitiv das Signal an (OSZI), Portdirection steht auf Eingang. Die Konfigurationsregister der Timer: Timer1: TCCR1A: 0b00000000 ;OC1A/OC1B disconnected, Normal Mode, kein Force Output TCCR1B: 0b00000111 ;ext. Signal an T1, rising edge Timer2: TCCR2: 0b00001111 ;CTC Mode, Prescaler 1024 OCR2: 31 ;ca. 65ms Ereignisse zählen bei 1Mhz SystemTakt Zu Beginn des Messvorgangs setze ich die Counterregister zurück und warte dann auf den Output Compare Interrupt des Timer2. In der ISR stoppe ich dann T1 mit out TCCR1B, 0b00000000. Bei der Auswertung des Counterstandes habe ich aber festgestellt, dass dieser IMMER auf 0 steht. Die Reihenfolge beim Schreiben/Lesen des 16Bit Regisers stimmt. Also zuerst Highbyte dann Lowbyte schreiben und umgekehrt beim Lesen. Während des Lese/Schreibvorgangs sind auch keine Interrupts erlaubt. Leider bin ich im Moment mit meinem Latein am Ende. Wäre schön wenn mir jemand sagen könnte warum mein Counter nichts zählt. Vielen Dank schon mal Holger
Wenn du schon den Timer1 des mega32 benutzt, warum nicht die Input-Capture-Funktion? Das erleichtert einiges und spart den zweiten (Torzeit-) Timer. Siehe Datenblatt.
Hi Hab mir den InputCapture Mode schon mal angeschaut, aber ich bin nicht ganz durchgestiegen. Kannst du mir vielleicht auf die Sprünge helfen? Seh ich das richtig: -TCCR1A: 0b00000000 ;Normal Mode, nichts besonderes -TCCR1B: 0b01000000 ;InputCapture rising edge Die Capture Unit misst dann die Systemtaktzyklen zwischen zwei extern anliegenden steigenden Flanken und schreibt diese in ICR1?! In der zugehörigen ISR sollte man dann den Wert auslesen um ihn auswerten zu können. Gruß Holger
Die Input-Capture-Einheit benutzt den Timer1 mit dem eingestellten Prescaler. Beim Auslösen eines INTs (in deinem Fall bei steigender Flanke am Pin) schreibt der µC den Zählerstand des Timers in das Input-Capture-Register. Der Timer läuft dabei weiter. Also musst du in der Input-Capture-ISR den Timer auf null setzen, dann hast du einen sauberen Zähler, der im Verhältnis zur Taktfrequenz zählt. Natürlich musst du den Timer auch starten (mit einstellen des Prescalers). Hier ein kleines Beispiel zur Einstellug des Timer1:
1 | TCCR1A = 0; // |
2 | TCCR1B |= _BV(CS10)|_BV(ICNC1)|_BV(ICES1); // Teiler /8, IC-Noise-canceller, rising edge |
3 | TIFR |= _BV(ICF1); // Flags löschen |
4 | TIMSK |= _BV(TICIE1); // IC-Interrupt freigeben |
Achso, programmierst du überhaupt in C? Die ISR würde so aussehen:
1 | SIGNAL (SIG_INPUT_CAPTURE1) // |
2 | {
|
3 | TCNT1 = 0; // Zähler rücksetzen |
4 | Counter1 = ICR1; // ICR-Register auslesen |
5 | }
|
Die Variable 'Counter1' muss als 'volatile' initialisiert werden. Mit ihr wird der Inhalt des ICR weiterverarbeitet.
"Also musst du in der Input-Capture-ISR den Timer auf null setzen" muss man gar nicht. Lass den Zähler weiterlaufen und bilde die Differenz zwischen dem aktuellen und dem letzten capture-Wert. Mit dem Rücksetzen auf 0 handelst du dir unnötige Fehler ein. Rücksetzen auf Null passiert nicht synchron mit dem capture-Ereignis (das allein wäre noch nicht weiter tragisch, da jedesmal der gleiche Fehler auftritt), aber der MC kann sich zum capture-Zeitpunkt in einer anderen ISR befinden, der capture-Wert ist korrekt, aber das Rücksetzen kommt verzögert.
Hast du völlig Recht mit dem Fehler, wenn ander INTs aktiv sind. Ich wollte es für den Anfang nicht unnötig verkomplizieren. Wenn der Zähler weiterläuft müssen die Überläufe berücksichtigt werden (sollten sie sowieso, z.B. zur Fehlerüberwachung falls der Geber ausfällt).
Power wrote: > Wenn der > Zähler weiterläuft müssen die Überläufe berücksichtigt werden Nein, müssen sie nicht. Der Zähler zählt im Ring (Modulo 2^16). Es muss allerdings ein geeigneter Vorteiler eingestellt werden, damit der Timer die Ereignisse "in einer Runde" erfassen kann. Das freie Durchlaufen lassen des Timers ermöglicht auch die Nutzung der Compare-Interrupts für andere Zwecke (zusätzlich zum Capture-Int.). Einer davon kann ganz elegant zum Prüfen auf Signal-Plausibilität herangezogen werden, indem man im Capture-Interrupt den Comp-Termin auf Capture-Zeit minus 1 setzt und bei einem auftretenden Capt-Interrupt (über Semaphores) die folgende Messung für ungültig erklärt. ...
>damit der Timer die Ereignisse "in einer Runde" erfassen kann.
Na das meinte ich doch! Vielleicht etwas unglücklich ausgedrückt. ;)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.