Forum: Mikrocontroller und Digitale Elektronik Arduino (Atmega328P) Timer overflow mit polling


von Andreas R. (andreasr2)


Angehängte Dateien:

Lesenswert?

Guten Tag und frohe Weihnachten in die Runde ...

Ich möchte den Overflow eines Atmega328P Timers nicht über einen 
Interrupt sonder via polling erfassen. Das Programm im Anhang soll das 
versuchen. Timer 1 lifert ca. alle 4 s einen Overflow (hochzählen bis 
2^16 -1, Prescaler 1024, CPU Takt 16 Mhz). Der Timer Overflow Interrupt 
ist ausgeschaltet. Ich habe im Handbuch nichts darüber gefunden, das das 
TOV Bit in TIRF1 nur gesetzt wird, wenn der entsprechende Interrupt 
enabled ist. Beim Overflow wird das Bit auf 0 gesetzt, eine 1 
kennzeichnet hier den nicht-overflow Zustand (so interpretiere ich das 
Datenblatt). Also sollte das doch mit Polling funktionieren.

In der main loop wird das TOV Bit im TIFR1 alle 500µs abgefragt, und je 
nach Ergebnis eine Ausgabe angezeigt. Ggf. bit das TOV bit wieder 
deaktiviert.

Ich würde jetzt alle 4 s eine Reaktion in der Ausgabe erwarten, aber das 
passiert nicht. Keine Ahnung was da los ist, vielleicht bin ich nur 
betriebsblind :(

Wer eine Idee hat, wie das Problem zu lösen ist ... ich würde mich feuen

VG, Andreas

von Marco (Gast)


Lesenswert?

Du könntest dir bei jeder Abfrage den aktuellen Timerstand merken und 
beim nächsten Aufruf mit dem dann aktuellen Zählerstand vergleichen. Ist 
der momentane Zählerstan kleiner als der beim letzten Aufruf, ist ein 
Überlauf passiert.

von Stefan F. (Gast)


Lesenswert?

> Wer eine Idee hat, wie das Problem zu lösen ist .

Welches Problem?

Du hast eine überzeugende Idee geäußert und sie bereits mit dem 
Datenblatt abgeglichen. Ich sehe da kein Problem.

Tu es!

von Andreas R. (andreasr2)


Lesenswert?

Das stimmt .... beantwortet aber noch nicht die Frage, warum es mit 
Polling des TOV Flag nicht klappt.

von Karl M. (Gast)


Lesenswert?

Hallo Andreas,

Du solltest Dir immer das Datenblatt zu deinem AVR µC aufmachen und auch 
lesen!

Das zeigt dieser falsche Kommentar in deinem Code
"// TOV-bit auf 1, somit nicht gesetzt?"

Siehe Abschnitt 16.11.9
*TIFR1 – Timer/Counter1 Interrupt Flag Register*

Bit 0 – TOV1: Timer/Counter1, Overflow Flag
The setting of this flag is dependent of the WGM13:0 bits setting. In 
Normal and CTC modes, the TOV1 Flag is set
when the timer overflows. Refer to Table 16-4 on page 133 for the TOV1 
Flag behavior when using another
WGM13:0 bit setting.
TOV1 is automatically cleared when the Timer/Counter1 Overflow Interrupt 
Vector is executed. Alternatively, TOV1
can be cleared by writing a logic one to its bit location.


Alle Welt schreibt
1
if (TIFR1 & (1<<TOV1)) {}
 nur Du nicht, warum?

Ein Hinweis:
ja man kann einen Überlauf abfragen, muss dann auch gleich das Flag/ 
Signal auch selbst wieder löschen.

Bei Dir also das Bit TOV1 "Timer/Counter1, Overflow Flag", dafür gibt es 
eine besondere Zuweisung.

von Karl M. (Gast)


Lesenswert?

Hallo,

auch liest sich diese Zeile einfacher, wenn man die Bit-Namen CS12, CS11 
und CS10 verwendet:
*TCCR1B – Timer/Counter1 Control Register B*
1
TCCR1B = (1<<CS12)^(0<<CS11)^(1<<CS10);

von Andreas R. (andreasr2)


Lesenswert?

Karl M. schrieb:
> Bit 0 – TOV1: Timer/Counter1, Overflow Flag
> The setting of this flag is dependent of the WGM13:0 bits setting. In
> Normal and CTC modes, the TOV1 Flag is set
> when the timer overflows. Refer to Table 16-4 on page 133 for the TOV1
> Flag behavior when using another
> WGM13:0 bit setting.
> TOV1 is automatically cleared when the Timer/Counter1 Overflow Interrupt
> Vector is executed. Alternatively, TOV1
> can be cleared by writing a logic one to its bit location.
>
> Alle Welt schreibt if (TIFR1 & (1<<TOV1)) {} nur Du nicht, warum?

ad 1: Da steht doch "Alternatively, TOV1 can be cleared by writing a 
logic one to its bit location.

Also ist 1 der nicht aktive Zustand und 0 siganlisiert den stattgehabten 
Überlauf.

ad 2: In einer Headerdatei steht "#define TOV1 0", d.h. (1<<TOV1) ist 
0x01 und genau das steht da.

von Karl M. (Gast)


Lesenswert?

Hallo Andreas Ru,

Andreas R. schrieb:
> Karl M. schrieb:
>> Bit 0 – TOV1: Timer/Counter1, Overflow Flag
>> The setting of this flag is dependent of the WGM13:0 bits setting. In
>> Normal and CTC modes, the TOV1 Flag is set
>> when the timer overflows. Refer to Table 16-4 on page 133 for the TOV1
>> Flag behavior when using another
>> WGM13:0 bit setting.
>> TOV1 is automatically cleared when the Timer/Counter1 Overflow Interrupt
>> Vector is executed. Alternatively, TOV1
>> can be cleared by writing a logic one to its bit location.
>>
>> Alle Welt schreibt if (TIFR1 & (1<<TOV1)) {} nur Du nicht, warum?
>
> ad 1: Da steht doch "Alternatively, TOV1 can be cleared by writing a
> logic one to its bit location.

Ja genau, wenn man kein interrupt service routine definiert hat, muss 
man es selbst machen !

Also im Programm machen man dies genauso wie folgt: man muss Schreiben 
TIFR1 = (1<<TOV1);

> Also ist 1 der nicht aktive Zustand und 0 siganlisiert den stattgehabten 
Überlauf.

Nein. Du kannst gerne diskutieren, aber das steht dort nicht!

> ad 2: In einer Headerdatei steht "#define TOV1 0", d.h. (1<<TOV1) ist
> 0x01 und genau das steht da.

Ja und ?
Ich habe nicht geschrieben, das 1 != (1<<TOV1) in genau diesem Fall 
ist.

Frage dich doch bitte warum man TOV1, wenn es kein Mensch nutzen soll.
Es ist viel einfacher und portabel mit den Bit-Namen zu arbeiten, auch 
vermeidet man Konvertierungsfehler.

von Karl M. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Andreas,
noch ein Argument gegen deine Interpretation des englischen Textes.
Im Datenblatt findet man immer die Initialisierungswerte für jedes 
Register.
Hier TIFR1 = 0x00.

_Angenommen_: 0 würde einen aktiven Zustand beschreiben, wann würde 
ohne Programmausführung sofort ein Timer1 Überlauf signalisiert, der 
auch gelöscht würde!

Siehe Bild.

von Andreas R. (andreasr2)


Lesenswert?

Da hast Du recht. Ich habs sorumm probiert und es scheint zu klappen.

Es bleibt die Frage, warum im Datenblatt steht, das das Schreiben einer 
1 das Register löscht??

von Stefan F. (Gast)


Lesenswert?

Wenn jemand schreibt "this flag is set" dann meint er damit immer, dass 
das Bit auf HIGH gesetzt wird. Es sei denn, im selben Absatz steht etwas 
anderes.

Komische negative Logik gibt es bei AVR nur bei den Fuses.

von Karl M. (Gast)


Lesenswert?

Andreas R. schrieb:
> Es bleibt die Frage, warum im Datenblatt steht, das das Schreiben einer
> 1 das Register löscht??

Du meinst DAS Bit TOV1 im Register TIFR1, nun weil es da steht.

von bernhard (Gast)


Lesenswert?

Andreas R. schrieb:
> Es bleibt die Frage, warum im Datenblatt steht, das das Schreiben einer
> 1 das Register löscht??

Na ja, Atmel hat seinen µC so gebaut und deshalb das auch ins Datenblatt 
geschrieben. So ein Interruptflag ist übrigens kein Register sondern ein 
Bit in einem Register.

von Stefan F. (Gast)


Lesenswert?

> Es bleibt die Frage, warum im Datenblatt steht, das das Schreiben einer
> 1 das Register löscht??

Das ist nicht ungewöhnlich, auch nicht bei anderen Mikrocontrollern.

von Andreas R. (andreasr2)


Lesenswert?

Karl M. schrieb:
> Ja genau, wenn man kein interrupt service routine definiert hat, muss
> man es selbst machen !
>
> Also im Programm machen man dies genauso wie folgt: man muss Schreiben
> TIFR1 = (1<<TOV1);

Aber dann wäre ja das TOV1 Bit auf 1 gesetzt!?!

von Stefan F. (Gast)


Lesenswert?

> Es bleibt die Frage, warum im Datenblatt steht, das das Schreiben einer
> 1 das Register löscht??

> Aber dann wäre ja das TOV1 Bit auf 1 gesetzt!?!

kann es sein, dass du deine eigene Aussage nicht verstanden hast? Wenn 
du eine 1 in dieses Bit schreibst, wird es auf 0 zurück gesetzt.

Das ist wie die Störungs-Lampe an der Gasheizung. Drückst du drauf, geht 
sie aus.

von Karl M. (Gast)


Lesenswert?

Andreas R. schrieb:
> Aber dann wäre ja das TOV1 Bit auf 1 gesetzt!?!

JA das ist doch das Ziel, dadurch wird das Bit gelöscht und bei zurück 
lesen erhält man eine "0", siehe das Datenblatt.

von Stefan F. (Gast)


Lesenswert?

Ich glaube, der TO unterliegt hier dem Irrtum, Register wie 
Speicherzellen zu betrachten. Das ist aber nicht der Fall.

Tatsächlich können Schreibzugriffe sogar ganz woanders hin gelangen, als 
Lesezugriffe. Das haben wir zum Beispiel beim seriellen Port.

Wenn man das UDR Register liest, erhält man das zuletzt empfangene Byte.
Wenn man das UDR Register beschreibt, wird es bei nächster Gelegenheit 
gesendet. Das sind in diesem Fall zwei völlig unabhängige Funktionen, wo 
das Schreiben in keinem Zusammenhang zum Lesen steht.

von Andreas R. (andreasr2)


Lesenswert?

Stefan U. schrieb:
> Ich glaube, der TO unterliegt hier dem Irrtum, Register wie
> Speicherzellen zu betrachten. Das ist aber nicht der Fall.
>

Diesem Irrtum bin ich tatsächlich unterlegen. Danke für diesen 
konstuktiven Hinweis :)

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.