Forum: Mikrocontroller und Digitale Elektronik ATmega32 Timer/Counter1 Problem


von Holger (Gast)


Lesenswert?

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

von Power (Gast)


Lesenswert?

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.

von Holger (Gast)


Lesenswert?

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

von Power (Gast)


Lesenswert?

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

von Power (Gast)


Lesenswert?

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.

von crazy horse (Gast)


Lesenswert?

"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.

von Power (Gast)


Lesenswert?

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).

von Hannes L. (hannes)


Lesenswert?

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.

...

von Power (Gast)


Lesenswert?

>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
Noch kein Account? Hier anmelden.