Forum: Compiler & IDEs Timer Problem


von Fabian (Gast)


Lesenswert?

Hallo,

ich bin gerade dabei etwas den Umgang mit GCC zu lernen und bin dabei
auf folgendes Problem gestoßen.

Bei einem Timer gibt es doch im TIFR ein Overflow Flag namens TOV
welches beim Timerdurchlauf auf "1" gesetzt wird und welches man dann
selbst wieder auf "0" setzen muss, damit es beim nächsten Durchlauf
wieder auf "1" gesetzt wird. Richtig?????.

So nun habe ich mir einen 8-Bit timer gebastelt und wollte das TOV Flag
abfragen dann das Prog. in eine If Abfrage laufen lassen und dann das
TOV flag wieder auf "0" setzen.

Um das TOV Flag auf "0" zu setzen habe ich folgenden Befehl
verwendet.

TIFR &=~ (1<<TOV0);

leider klappt es nicht. das Flag bleibt einfach "1"

Nun ist mir aber aufgefallen, dass ich wenn ich den Befehl zum setzen
des Flags sprich

TIFR |= (1<<TOV0);

einsetze, das Flag zurückgesetzt wird.... Das verwirrt mich nun
etwas..
Kann mir jemand erklären, was ich falsch gemacht habe??

danke

Fabian

von Volker (Gast)


Lesenswert?

Hallo Fabian,

das ist völlig normal. Hier ein Auszug aus einem AVR-Datenblatt.
----
TOV0 is cleared by
hardware when executing the corresponding interrupt handling vector.
Alternatively,
TOV0 is cleared by writing a logic one to the flag.
----

Es wird also geöscht, wenn man eine 1 reinschreibt.


Bin ich auch schon mal drüber gestolpert.

Gruß Volker

von Fabian (Gast)


Lesenswert?

Hm das is ja irgendwie seltsam. Naja okay wenn man es weiß.

Okay aber vielen Dank dann is mein Syntax schonmal nicht Falsch..

von Peter D. (peda)


Lesenswert?

Ich sach mal, jeder der die AVRs anfäßt, stolpert unweigerlich
mindestens einmal darüber (ich auch).

Verstehen kann man es nicht, man muß es eben akzeptieren.


Beim 8051 löscht man die Bits mit ner 0, wie es sich gehört und man
kann sie sogar setzen (= Software-Interrupt), gefällt mir viel besser.


Peter

von Michael U. (Gast)


Lesenswert?

Hallo,

@Peter Dannegger:

dazu muß man nicht erst auf den AVR warten, da bin ich schon vor Jahren
drüber gestolpert. Weiß nicht mehr, ob Z80 oder 6510 oder beide. Ist
zumindest nicht neu, das Problem. ;)

Gruß aus Berlin
Michael

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Verstehen kann man es nicht, man muß es eben akzeptieren.

Doch, man könnte in der FAQ nachlesen, warum das so Sinn hat:

http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_intbits

Natürlich hat es nur bei denen richtig Sinn, die in einem eigenen
Register liegen, das ausschließlich Interrupt-Flags hat.  Bei allen
anderen kann man ja nicht so ohne weiteres ein 1-Bit drüberbügeln
bzw. man muss sich den Status der restlichen Bits anderweitig merken.
Dennoch wurde es wohl bei allen Interruptflags, die man überhaupt ,,zu
Fuß'' löschen kann, so gemacht, vermutlich aus Konsistenzgründen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Okay aber vielen Dank dann is mein Syntax schonmal nicht Falsch..

Doch, ist es, wiederum siehe FAQ.

TIFR |= (1<<TOV0);

riskiert eine race condition, während

TIFR = (1<<TOV0);

diese vermeidet.  Sieht auf den ersten Blick widersinnig aus,
ist aber so.  Ist natürlich egal, wenn du keinen weiteren
Timer-Interrupt benutzt, aber man gewöhnt es sich besser gleich
richtig an.

von Fabian (Gast)


Lesenswert?

Puh Race Condition?
Ich bin erst seit 3 Tagen dabei also weiß ich nicht gerade worum es
geht.
Ich dachte durch |= wird das Ergebnis mit dem Register "Verodert"
oder nicht?

von Michael U. (Gast)


Lesenswert?

Hallo,

zwar ist C nicht meine Stärke, aber das Problem ist, wenn Du ihm sagst
er soll "verodern", dann holt er den Wert in ein Register, führt das
OR aus und schreibt zurück.
Da aber in diesem Register mit dem Schreiben einer 1 das Flag gelöscht
wird, werden auch alle anderen INT-Flags mit gelöscht, das aber soll ja
nicht passieren.

Eine "race condition" sagt nur, daß unter Umständen beim
Zusammentreffen bestimmter Umstände ein fehlerhaftes Verhlaten
auftritt. Sowas sollte man möglichst früh erkennen und immer
vermeiden.

Die meisten Fehler baut man sich in Programme ein, weil man zwar den
gewollten Ablauf x-mal durchdenkt, die Überprüfung, was passiert bei
allen anderen möglichen Umständen, aber versäumt.

Naja, das geht nicht nur Dir so. ;)

Gruß aus Berlin
Michael

von Fabian (Gast)


Lesenswert?

Achso.... Okay denn is es klar. Nochmals vielen Dank.

Eine kleine Frage hätte ich aber noch zu dem Thema.
Kann ich auf die einzelnen Bits des TCNT Registers nicht direkt
zugreifen?
Ich arbeite mit dem GCC Tutorial dieser Seite und dort ist (falls es
jmd. vorliegen hat) auf Seite 36 das TCNT0 Register abgebildet. So nun
spricht man die einzelnen Bits ja mit z.B.

TCNT0 |=(1<<Bitname);

nur bei den Bit´s steht im Tutorial kein Name.
Heisst das ich kann nur indirekt drauf zugreifen durch
TCNT0 |=0xff;

Es macht zwar keinen direkten Sinn die Bits zu beschreiben, es ist eher
so ne allgemeine Frage, wie man auf Bits zugreift, die keinen direkten
Namen haben?

von Michael U. (Gast)


Lesenswert?

Hallo,

naja, wie sollte ein Bit im TCNT0 auch sinnvoll heißen?
Die Namen sollen das Ganze ja nur lesbarer machen, wenn Du auf andere
Bits unbedingt einzeln zugreifen willst, kannst Du so machen, wie Du
schreibst oder Du benutzt die Bitnummer.

TCNT0 |=(1<<Bitnummer);  Bitnummer eben 0...7

Gru0 aus Berlin
Michael

von Fabian (Gast)


Lesenswert?

Achso das geht?
Okay vielen Dank... hätte ich eigentlich auch ma selbst drauf kommen
können.

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.