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
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
Hm das is ja irgendwie seltsam. Naja okay wenn man es weiß. Okay aber vielen Dank dann is mein Syntax schonmal nicht Falsch..
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
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
> 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.
> 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.
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?
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
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?
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.