Habe lange Erfahrung mit ATmega und ATxmega, habe aber mit ATtiny so gut
wie keine Erfahrung. Jetzt ist mir ein ATtiny85 über den Weg gelaufen
und ich habe ein paar Tests damit gemacht. Dabei ist mir aufgefallen,
das der Timer1 anderst gestrickt ist als der Timer0 und sich auch
anderst verhält, was ich mir nicht erklären kann. Speziell geht es hier
aber nur um das Überlaufflag TOV1. Das es auch noch andere Änderungen
des Timer1 gegenüber Timer0 gibt, habe ich schon im Datenblatt nachlesen
können.
Wenn ich z.B. Timer0 des ATtiny85 verwende kann ich damit ganz normal
eine Zeitschleife ausführen, so wie ich das auch von Atmega usw. her
kenne. Wie z.B. diese für den Timer0...
;----Timer Vorteiler einstellen und Timer läuft...
ldi temp, 0b00000101
out TCCR0B, temp
;----Programmschleife LED Blinker...
test:
sbi port_led, led_1
rcall warte_100ms
cbi port_led, led_1
rcall warte_100ms
rjmp test
;----Unterprogramm Warteschleife...
warte_100ms:
ldi temp, 0b00000000
out TCNT0, temp
in temp, TIFR
ori temp, 0b00000010
out TIFR, temp
warte_loop:
in temp, TIFR
sbrs temp, TOV0
rjmp warte_loop
ret
Ob mit dieser Warteschleife wirklich 100mS rauskommen oder nicht, ist
erst mal egal... darum geht es auch nicht.
Wenn ich aber das selbe mit dem Timer1 mache, (Natürlich auch die
entsprechenden Verwendung der Timer1 Register und des TOV1 Bit2 des
TIFR!) Dann wird die Warteschleife "warte_100ms" das erste mal
ordentlich durchgeführt, aber immer und grundsätzlich das zweite mal
nicht! Grundsätzlich wird die Warteschleife immer nur jedes zweite Mal
richtig verarbeitet.
Jetzt habe ich feststellen können, das das Überlaufbit TOV1 bei jedem
zweiten Durchlauf der Warteschleife nicht gelöscht wird, obwohl ich eine
"1" auf das Bit2 des TIFR schreibe und die Wartezeit somit nicht
stattfindet.
Im Datenblatt habe ich unter der Registerbeschreibung für TIFR folgendes
gefunden...
"TOV1 is cleared, after synchronization clock cycle, by writing a
logical one to the flag".
Daraufhin habe ich das Problem so gelöst, das ich zweimal hintereinander
das TOV1 flag mit einer "1" beschreibe und dann ist es auch wirklich
immer gelöscht und das primitive Testprogramm funktioniert.
Nun aber zu meiner eigentlichen Frage:
Was muss ich mir unter "after synchronization clock cycle" denn
vorstellen? "after" was denn?
Aus dem Datenblatt werde ich nicht schlau, was es mit diese
synchronisation aufsich hat, wie bzw. warum sich diese auf das löschen
des Überlaufflags auswirkt und wie diese arbeitet/funktioniert und wie
man das TOV1 Bit denn dann richtig löscht?
Könnte mir bitte jemand mit ein paar Worten Beschreiben warum das so
beim Timer1 des ATtiny85 (oder aller ATtinys?) ist?
Tom schrieb:> in temp, TIFR> ori temp, 0b00000010> out TIFR, temp
Das ist definitiv unsinniger Code. Und nicht nur beim ATtiny, sondern
bei jedem AVR8. Lies' bitte das DB und versuche, zu verstehen, was da
zum Thema "strobe bits" geschrieben wird (leider ohne den Begriff zu
erwähnen).
Korrekt wäre:
> ldi temp, 0b00000010> out TIFR, temp
Naja, jedenfalls wäre es richtig, wenn auf Bitposition 1 tatsächlich das
TOV1-Flag wäre. Ist es aber nicht...
S. Landolt schrieb:> Hängt wohl damit zusammen, dass Timer1 auch asynchron laufen kann.> Einfach nach dem 'out TIFR' ein paar Takte warten, 3 scheinen zu> reichen.
Danke für den Tipp, der auch wirklich so funktioniert.
Scheinbar braucht der Timer1 halt wirklich 3 ganze Taktzyklen, bevor
eine Änderung des TIFR TOV1 Flags durch den "out TIFR" Befehl bewirkt
wird.
Ich habe jetzt mal meinen Programmcode mit 3 NOP´s abgeändert und das
funktioniert auch! Aber halt auch wirklich nur mit 3 NOP´s. Wenn ich nur
2 NOP´s mache dann geht es wieder nicht.
in temp, TIFR
ori temp, 0b00000100
out TIFR, temp
nop
nop
nop
Also dann verstehe ich auch wie die Zeichnung im Anhang bzw. von Seite
83 des Datenblattes zu verstehen ist.
Hier sind es zuerst ein halber Takt, dann ein ganzer Takt, dann nochmal
ein ganzer Takt und zum Schluss nochmal ein halber Takt. Also treten
dann immer die 3 Takte Verzögerung beim Timer1 auf, wenn im Datenblatt
von "after synchronisation..." gesprochen wird.
Ich kann mir zwar noch nicht wirkich erklären, warum das so ist, aber es
hilft doch zumindest das die Programme auch am Ende ohne Problem laufen.
Besten Dank noch mal für deinen Hinweis.
Jepp, so schreibt das ein Programmierer, der diesen Namen verdient. Ok,
über den Nutzen der Klammerung könnte man hier noch diskutieren, aber
sie schaden zumindest nicht. Auch mein Konzept ist: lieber ein
Klammerpaar zu viel, als eins zu wenig...
Hauptsache, es ist an der richtigen Stelle. Dann kann es Intentionen oft
besser dokumentieren als jeder Kommentar (auch wenn es syntaktisch
überflüssig ist).
Aber bei nur einem Term würde auch ich doch eher auf die Klammerung
verzichten...
Wenn wir aber schon bei unnötigen Hinweisen (oder gar Kritik?) sind:
ich habe mir ein macro puti (darf auch anders heißen) definiert und
schreibe folglich
Tom schrieb:> Scheinbar braucht der Timer1 halt wirklich 3 ganze Taktzyklen, bevor> eine Änderung des TIFR TOV1 Flags durch den "out TIFR" Befehl bewirkt> wird.
Nur dann, wenn er auch wirklich asynchron betrieben wird. Er kann ja
durchaus auch ganz normal synchron betrieben werden und verhält sich
dann auch ganz normal...
S. Landolt schrieb:> ori temp, 0b00000100> out TIFR, temp> funktioniert hier zwar, ist aber eigentlich falsch, denn eventuell> gesetzte weitere Flags in TIFR werden damit auch gelöscht, korrekt> wäreldi temp, (1<<TOV1)> out TIFR, temp
Danke für das Ansprechen des setzens des Bit´s für das TOV1 Bit.
Habe jetzt die Änderung auch so in meinem Programm gemacht. Ich wollte
es besonderst gut machen, das eventuelle andere Bit´s im TIFR Register
nioht beeinflusst werden. Aber wenn ich jetzt nochmal darüber nachdenke,
ist es ja klar. Wenn ein Bit bzw. Flag im Register TIFR bereits durch
irgendeine andere Aktion gesetzt worden wäre, würde ich dieses dann ja
auch mit löschen, was natürlich vollkommen falsch wäre...
Somit muss ich sagen, das auch C-hater damit geholfen hat.
Danke nochmals für die Hinweise.
c-hater schrieb:>> Nur dann, wenn er auch wirklich asynchron betrieben wird. Er kann ja> durchaus auch ganz normal synchron betrieben werden und verhält sich> dann auch ganz normal...
Ahhhhh.... Ich hatte gedacht, wenn ich nur den Vorteiler mit einem Wert
aktiviere, das ich dann im synchronen Betriebsmodus bereits wäre. Wenn
das nicht der Fall ist, wo oder wie oder was muss ich denn machen um in
den Synchronen Modus zu gelangen? Welche Register, welche Bit´s müssen
denn dafür gesetzt werden? Aus dem Datenblatt werde ich darüber nicht
schlau...
Kannst du mir da mal bitte Helfen?
Tja, Tom, so ist das mit den Überfliegern. Wahrscheinlich baut c-hater
auf seine Erfahrungen, z.B. mit ATmega328_Timer2. Auf seine Antwort bin
ich gespannt.
S. Landolt schrieb:> Haben Sie das mal ausprobiert, c-hater?
Praktisch? Ehrlicherweise: Nein. Polling ist nicht so mein Ding. Die
meisten Sachen mache ich in ISRs. Und da brauche ich mich bei den Timern
nie um den Reset des IRQ-Flags zu kümmern, das erledigt dann das System
für mich. Ohne Zusatzkosten...
Wäre also wirklich denkbar, dass ich das falsch sehe, dass also die für
den asynchronen Betrieb dokumentierten Delays auch im synchronen Betrieb
wirksam sind. Werde ich bei nächster Gelegenheit mal verifizieren.
Glücklicher Umstand: aktuelles Hobbyprojekt hat mal wieder einen Tiny85
als Target. Also könnte ich das wohl schon morgen mal abchecken...
Tom schrieb:> Ahhhhh.... Ich hatte gedacht, wenn ich nur den Vorteiler mit einem Wert> aktiviere, das ich dann im synchronen Betriebsmodus bereits wäre.
Bist du auch. Solange du PCKE in PLLCSR nicht setzt, ist der Timer in
der Systemtakt-Domäne.