Hallo,
ich möchte gerne auf einem ATmega 328p im Register TCCR2B die Bits CS22
und CS20 setzen und die Bits CS21 und WGM22 löschen.
Ich kann das in zwei Schritten mittels
1
TCCR2B|=((1<<CS22|(1<<CS20));
2
TCCR2B&=~((1<<WGM22)|(1<<CS21));
bewerkstelligen. Der Timer/Counter2 soll allerdings asynchron laufen und
ich müsste das Setzen erst abwarten (Prüfung des Bits TCR2BUB aus ASSR)
bevor ich den Löschvorgang starte. Die Werte landen ja erst in einem
temporären Register und würden ansonsten möglicherweise überschrieben.
Kann ich mit
Patrick S. schrieb:> Kann ich mit((1<<CS22|(1<<CS20)|(0<<WGM22)|(0<<CS21))irgendwie> arbeiten??
nein, weil das der Oder Operator ist. Und irgendwas | X = irgendwas und
eben nicht gelöscht.
Außerdem bringts dir von der Laufzeit her überhaupt nichts, es sieht nur
etwas unübersichtlicher aus
__avrdude schrieb:> nein, weil das der Oder Operator ist. Und irgendwas | X = irgendwas und> eben nicht gelöscht.
Ok, vielen Dank. Mir ist noch eingefallen, dass ich sowas wie
1
TCCR2B=((1<<CS22|(1<<CS20)|(0<<WGM22)|(0<<CS21))
machen könnte. Allerdings nur in diesem Fall, da die anderen Bits des
Registers auch 0 sein dürfen. Wäre allerdings unschön und bringt
vielleicht später komische Probleme hervor...
> Außerdem bringts dir von der Laufzeit her überhaupt nichts, es sieht nur> etwas unübersichtlicher aus
Wenn ich die Zuweisung in einem Schritt machen könnte, würde ich doch
etwas Zeit sparen?! So muss ich ja noch warten, dass die Daten aus dem
temporären Register in das Zielregister übertragen wurden und kann erst
dann die Bits löschen.
Patrick S. schrieb:> Ok, vielen Dank. Mir ist noch eingefallen, dass ich sowas wie TCCR2B => ((1<<CS22|(1<<CS20)|(0<<WGM22)|(0<<CS21)) machen könnte.
Könntest du machen - bringt aber nichts. Du solltest dein Verständnis
vom "|"-Operator (Bitweises ODER) noch deutlich vertiefen.
Patrick S. schrieb:> Wenn ich die Zuweisung in einem Schritt machen könnte, würde ich doch> etwas Zeit sparen?!
NEIN du sparst keine Zeit. An der Basis wird trotzdem dein Ausdruck
TCCR2B = ((1<<CS22|(1<<CS20)|(0<<WGM22)|(0<<CS21))
wie folgt ausgeführt
ldi REGISTER , (1<<CS22|1<<CS20|0<<WGM22|0<<CS21)
out TCCR2B , REGISTER
.
Wenn du gewisse Bits hast die nicht verändert werden sollen/dürfen...
dann bietet sich eine Ver(oder)ung oder Ver(und)ung an.
z.B. fürs setzen
in REGISTER , TCCR2B ; ins REGISTER laden
or REGISTER , (1<<CS22|1<<CS20|0<<WGM22|0<<CS21) ; REGISTER verodern
out TCCR2B , REGISTER ; Wert ins TCCR2B
laden
z.B. fürs löschen
in REGISTER , TCCR2B ; ins REGISTER laden
and REGISTER , (1<<CS22|1<<CS20|0<<WGM22|0<<CS21) ; REGISTER verodern
out TCCR2B , REGISTER ; Wert ins TCCR2B
laden
ACHTUNG dort wo eine 0 steht wird am Ende das Bit (falls gesetzt)
gelöscht.
Karl M. schrieb:> and REGISTER ,not (1<<CS22|1<<CS20|0<<WGM22|0<<CS21) ; REGISTER
Ging mir nur um das WIE. Der TO muss die Transferleistung selber bringen
falls der Hinweis überhaupt nützlich war
chris schrieb:> Patrick S. schrieb:>> Wenn ich die Zuweisung in einem Schritt machen könnte, würde ich doch>> etwas Zeit sparen?!>> NEIN du sparst keine Zeit. An der Basis wird trotzdem dein Ausdruck>> TCCR2B = ((1<<CS22|(1<<CS20)|(0<<WGM22)|(0<<CS21))>> wie folgt ausgeführt>> ldi REGISTER , (1<<CS22|1<<CS20|0<<WGM22|0<<CS21)> out TCCR2B , REGISTER> .
Das ist soweit klar. Das sind in diesem Fall 2 Assembler-Befehle und in
diesem Fall braucht jeder 1 Takt, damit insgesamt 2 Takte.
> Wenn du gewisse Bits hast die nicht verändert werden sollen/dürfen...> dann bietet sich eine Ver(oder)ung oder Ver(und)ung an.>> z.B. fürs setzen>> in REGISTER , TCCR2B ; ins REGISTER laden> or REGISTER , (1<<CS22|1<<CS20|0<<WGM22|0<<CS21) ; REGISTER verodern> out TCCR2B , REGISTER ; Wert ins TCCR2B> laden>> z.B. fürs löschen>> in REGISTER , TCCR2B ; ins REGISTER laden> and REGISTER , (1<<CS22|1<<CS20|0<<WGM22|0<<CS21) ; REGISTER verodern> out TCCR2B , REGISTER ; Wert ins TCCR2B> laden>> ACHTUNG dort wo eine 0 steht wird am Ende das Bit (falls gesetzt)> gelöscht.
Die Veroderung bzw. Verundung erfordern 3 ASM-Befehle und jeweils 3
Takte. Damit also 1 Takt mehr als die einfache Zuweisung (erste
Variante) und somit also auch mehr Zeit!
Ich weiß, dass mir dies in meinem Fall nichts bringt, da ich damit nicht
das erreiche, was ich vorhatte. Ich werde nun also in 3 Takten die
Veroderung durchführen und die gewünschten Bits setzen, dann x Takte
warten, bis das TCR2BUB Bit aus ASSR wieder 0 ist und im Anschluss noch
einmal 3 Takte verwenden, um über die Verundung die gewünschten Bits zu
löschen. Macht 6 + x Takte.
Es hätte ja sein können, dass es eine (mir unbekannte) C-Anweisung gibt,
der ich sagen kann lösche die Bits t, u und setze die Bits v, w aus
Register k. Meinetwegen dürfte diese ja auch 4, 5, 6 oder 7 Takte
benötigen. So wäre ich dann aber garantiert in den 4-7 Takten fertig.
Das Warten auf TCR2BUB könnte ich mir komplett sparen, da ich danach
nicht noch einmal auf TCCR2B zugreife (bzw. erst sehr viel später, wenn
der Wert aus dem temporären Register garantiert schon in das
Zielregister geschrieben wurde). Ich würde mir so also die x Takte
sparen.
So habe ich allerdings immer eine zusätzliche Verzögerung, selbst wenn
der Wert aus dem temporären Register zufällig schon übernommen wurde.
Das kommt halt daher, dass ich noch sowas wie
1
while(ASSR&(1<<TCR2BUB));
einbauen muss. Auf Assembler-Ebene also wieder IN, ANDI, BRNE (oder so
ähnlich) mit vermutlich um die 5 Takten, das ganze dann noch
multiplizert mit der Anzahl der Schleifendurchläufe. So ganz genau lässt
sich das ja auch nicht sagen, da die Branches unterschiedlich lange
brauchen.
So viel also zu meiner Veranlassung hier nachzufragen. Ein klares "Nein,
geht nicht." hätte mir schon gereicht. :D
chris schrieb:> Ging mir nur um das WIE. Der TO muss die Transferleistung selber bringen> falls der Hinweis überhaupt nützlich war
Wenn ich ehrlich bin, war der Hinweis nicht sooo nützlich. Ich kenne
zwar auch die Assembler-Befehle, aber davon auszugehen und dann einfach
Assembler schreiben, obwohl ich C-Code gesucht habe... Naja, ich glaube
die Problematik, auf die ich hinaus wollte, war auch nicht so ganz klar.
;)
Patrick S. schrieb:> Ich weiß, dass mir dies in meinem Fall nichts bringt, da ich damit nicht> das erreiche, was ich vorhatte. Ich werde nun also in 3 Takten die> Veroderung durchführen und die gewünschten Bits setzen, dann x Takte> warten, bis das TCR2BUB Bit aus ASSR wieder 0 ist und im Anschluss noch> einmal 3 Takte verwenden, um über die Verundung die gewünschten Bits zu> löschen. Macht 6 + x Takte.
Nein geht doch einfacher mit 4 Takten
in REGISTER , TCCR2B ; ins REGISTER laden
and REGISTER , (1<<CS22|1<<CS20|0<<WGM22|0<<CS21) ; einzelen Bits
löschen
or REGISTER , (y<<CS22|y<<CS20|y<<WGM22|y<<CS21) ; REGISTER verodern
out TCCR2B , REGISTER ; Wert ins TCCR2B
Patrick S. schrieb:> Wenn ich ehrlich bin, war der Hinweis nicht sooo nützlich. Ich kenne> zwar auch die Assembler-Befehle, aber davon auszugehen und dann einfach> Assembler schreiben, obwohl ich C-Code gesucht habe... Naja, ich glaube> die Problematik, auf die ich hinaus wollte, war auch nicht so ganz klar.
Um Wissen zu erlangen gibt es nie einen direkten Weg.
Ich kann kein C deshalb ASM sry. Könnte ich es hättest du schon ein
Nein/Ja geht/nicht bekommen ;)
chris schrieb:> Nein geht doch einfacher mit 4 Takten>> in REGISTER , TCCR2B ; ins REGISTER laden> and REGISTER , (1<<CS22|1<<CS20|0<<WGM22|0<<CS21) ; einzelen Bits> löschen> or REGISTER , (y<<CS22|y<<CS20|y<<WGM22|y<<CS21) ; REGISTER verodern> out TCCR2B , REGISTER ; Wert ins TCCR2B
Im wesentlichen müsste das ja der C-Code von peda sein, übersetzt in
Assembler. y<<CS22 habe ich so aber wiederum noch nicht gesehen. Kannst
du mir sagen, was das bedeutet oder ist das ein Tippfehler?
AND und OR müssten auch ANDI bzw. ORI sein, wenn ich das richtig im Kopf
habe und bis auf WGM22 bzw. CS21 müssen alle anderen Bits auf 1 gesetzt
werden, um seiteneffektfrei zu arbeiten. Alternativ mit NOT arbeiten.
Ich hätte peda's Code vermutlich so übersetzt, ohne den getestet zu
haben:
Patrick S. schrieb:> Im wesentlichen müsste das ja der C-Code von peda sein, übersetzt in> Assembler.
keine Ahnung wessen Code das ist aber mit Überlegung wo man was wie
braucht kommt man doch selber drauf
Patrick S. schrieb:> y<<CS22 habe ich so aber wiederum noch nicht gesehen. Kannst> du mir sagen, was das bedeutet oder ist das ein Tippfehler?
Das y ist ein PLatzhalter je nachdem was du brauchst 0/1.
jep stimmt mit dem ANDI/ORI, da es Konstante mit Register verknüpft, das
ist mein Fehler. 0.o
Patrick S. schrieb:> bis auf WGM22 bzw. CS21 müssen alle anderen Bits auf 1 gesetzt> werden,
Jep stimmt aber nur beim ANDI. Das ORI sagt wieder welche Bits gesetzt
werden sollen dh es müssen nur die eingetragen werden die eine 1
bekommen sollen.
ACHTUNG das war mir vorher nicht aufgefallen ist, guck mal in das
DATENBLATT du möchtest/musst zwei verschiedene Register ansprechen,
TCCR2A und TCCR2B!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Im TCCR2A WGM20/21 ändern und im TCCR2B CS22/21/20 WGM22 ändern
IN REGISTER, TCCR2B
ANDI REGISTER, (0<<CS22|0<<CS21|0<<CS20|0<<WGM22|1<<FOC2B|1<<FOC2A), nur
löschen
ORI REGISTER, (y<<CS22|y<<CS21|y<<CS20|y<<WGM22)
OUT TCCR2B , REGISTER
IN REGISTER, TCCR2A
ANDI REGISTER,
(0<<WGM20|0<<WGM21|1<<COM2B0|1<<COM2B1|1<<COM2A0|1<<COM2A1), nur löschen
ORI REGISTER, (y<<WGM20|y<<WGM21)
OUT TCCR2A , REGISTER
Und nutze den Simulator wenn du einen hast und probiers durch denn dafür
is das Ding da. ;)
Um auf deine Takte anzusprechen bei 4Mhz sind es pro Takt 250ns, 500ns
oder 750ns in der Ausführungszeit da sind diese 8 Befehle n Klacks
dagegen. Nach 8*250ns = 2µs ist der Drops gelutscht. :))
Patrick S. schrieb:> y<<CS22 habe ich so aber wiederum noch nicht gesehen. Kannst> du mir sagen, was das bedeutet oder ist das ein Tippfehler?
y ist hoffentlich ein Ganzzahl und die wird mit dem Befehl CS22-mal nach
links geschoben. Was der Autor sich dabei gedacht hat und was er da
hingeschrieben hat, mögen wohl zwei verschiedene Dinge sein.
Sinnvoll wäre, wenn y einen Clock Select Wert zwischen 0 und 7, enthält
chris schrieb:> ACHTUNG das war mir vorher nicht aufgefallen ist, guck mal in das> DATENBLATT du möchtest/musst zwei verschiedene Register ansprechen,> TCCR2A und TCCR2B!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Die Werte im zweiten Register habe ich schon längst gesetzt. Das war ja
auch nicht das Problem, ich wollte ja eigentlich nur eine Lösung
möglichst effizient Werte in einem Register zu setzen und andere zu
löschen.
Das ist eines der Gründe, warum ich kein C mehr programmiere. Ich weiss
genau, was registerseitig passieren soll, aber habe keine Ahnung, was C
aus meinen Syntaxfantasien letztendlich umsetzt und jedes mal in den
generierten ASM-Code schauen war mir zu blöd.
Als Assemblerprogrammierer nutzt man eigentlich auch nicht andi und ori,
sondern cbr und sbr für Clear Register Bits und Set Register Bits. Dann
ist das ganze auch intuitiver zu lesen.
in
cbr
sbr
out
und fertig.
Und nein, ich habe nichts gegen C. Ich würde Programme für den PC nie in
ASM schreiben, sondern in C. Aber für Mikrocontroller, die nur ein paar
Pins rumtoggeln und ab und zu mal ein SPI Display ansteuern war es
bisher immer die passendere Sprache.
Hannez schrieb:> Als Assemblerprogrammierer nutzt man eigentlich auch nicht andi und ori,> sondern cbr und sbr für Clear Register Bits und Set Register Bits. Dann> ist das ganze auch intuitiver zu lesen.>> in> cbr> sbr> out
Guter Tipp, danke. Ich hätte vermutlich auch eher ASM genommen,
allerdings wollte ich mir die AVR-Programmierung mit C mal genauer
ansehen und zudem bin ich daran ein Projekt umzusetzen, was vom Umfang
her etwas größer ist. Bin gerade am RTC-Modul, USART habe ich schon,
dann noch Display und verschiedene Aktoren ansteuern, Sensoren abfragen,
Textausgaben, UI und letztendlich soll das ganze noch eine gewisse
Intelligenz (AI) haben, das war mir für ASM dann doch zu aufwändig. :)
Um es übersichtlich hinzuschreiben und kein Assembler heranzuziehen,
kannst du natürlich auch einfach eine temporäre Variable verwenden. gcc
sollte dann eigentlich automatisch mit Registern arbeiten...
Hannez schrieb:> aber habe keine Ahnung, was C> aus meinen Syntaxfantasien letztendlich umsetzt
Das ist doch ganz einfach:
Wenn Du 2 Zuweisungen zu einem IO-Register hinschreibst, muß der
Compiler auch 2 Zuweisungen ausführen.
Zugriffe auf IO-Register können nämlich Seiteneffekte haben und daher
sind IO-Register als volatile deklariert.
Wenn Du aber nur eine Zuweisung hinschreibst, macht der Compiler auch
nur eine Zuweisung, wer hätte das gedacht.
Auf der rechten Seite einer Zuweisung können beliebig lange Ausdrücke
stehen, der Parser des Compilers kennt da kein Limit.
https://msdn.microsoft.com/de-de/library/474dd6e2.aspx
Hannez schrieb:> Das ist eines der Gründe, warum ich kein C mehr programmiere. Ich> weiss> genau, was registerseitig passieren soll, aber habe keine Ahnung, was C> aus meinen Syntaxfantasien letztendlich umsetzt und jedes mal in den> generierten ASM-Code schauen war mir zu blöd.>> Als Assemblerprogrammierer nutzt man eigentlich auch nicht andi und ori,> sondern cbr und sbr für Clear Register Bits und Set Register Bits. Dann> ist das ganze auch intuitiver zu lesen.>> in> cbr> sbr> out>> und fertig.
Nun cbr und andi mit not des Arguments sind das gleiche, auch als
Assembler Kodierung.
Entsprechend gilt dies für sbr und ori..
Peter D. schrieb:> Wenn Du aber nur eine Zuweisung hinschreibst, macht der Compiler auch> nur eine Zuweisung, wer hätte das gedacht.
Nicht unbedingt, da es sich um AND und OR in derselben Zuweisung
handelt.
Peter D. schrieb:> TCCR2B = (TCCR2B & ~((1<<WGM22)|(1<<CS21))) | ((1<<CS22|(1<<CS20));
Das ist nur eine Zuweisung in C, aber mindestens 2 in ASM.
Marc V. schrieb:> Das ist nur eine Zuweisung in C, aber mindestens 2 in ASM.
Das ist der Vorteil von C, wichtig ist immer nur, was hinten rauskommt.
Ob dabei Zwischenergebnisse temporär in CPU-Registern oder RAM abgelegt
werden, interessiert den Programmierer nicht und sind auch keine
Zuweisungen. CPU-Register/RAM sind ja danach wieder frei verfügbar.
Hannez schrieb:> Als Assemblerprogrammierer nutzt man eigentlich auch nicht andi und ori,> sondern cbr und sbr für Clear Register Bits und Set Register Bits. Dann> ist das ganze auch intuitiver zu lesen.>> in> cbr> sbr> out>> und fertig.
Nicht immer.
Nibbles werden immer mit AND ausgeblendet. Um es aber übersichtlicher
zu machen, kann man vorher LoNibble und HiNibble definieren.
Peter D. schrieb:> Ob dabei Zwischenergebnisse temporär in CPU-Registern oder RAM abgelegt> werden, interessiert den Programmierer nicht und sind auch keine> Zuweisungen. CPU-Register/RAM sind ja danach wieder frei verfügbar.
Stimme ich zu, aber der TO wollte wissen ob das irgendwie in einem
Schritt (ein Befehl) zu machen ist.
Es geht nicht und daher ist deine Lösung zwar kürzer und eleganter aber
man muss da schon ganz genau die Klammern zählen.
Deswegen wären zwei Zeilen übersichtlicher und besser zu verstehen
- von der Codegröße und Schnelligkeit besteht da kein Unterschied.
Peter D. schrieb:> Das ist der Vorteil von C, wichtig ist immer nur, was hinten rauskommt.
Und auch der Nachteil - Unübersichtlichkeit.
Marc V. schrieb:> aber der TO wollte wissen ob das irgendwie in einem> Schritt (ein Befehl) zu machen ist.
Nö, er wollte wissen, ob man den Seiteneffekt Synchronisierung nur
einmal abwarten muß und das kann man bei nur einer Zuweisung.
Marc V. schrieb:> aber> man muss da schon ganz genau die Klammern zählen.
Nö, das macht der Editor (z.B. Notepad++) für Dich. Einfach auf eine
Klammer gehen und er zeigt die dazu gehörende schließende oder
umgekehrt.
Ich bevorzuge allerdings die Vorrangregeln:
Peter D. schrieb:> Marc V. schrieb:>> aber der TO wollte wissen ob das irgendwie in einem>> Schritt (ein Befehl) zu machen ist.>> Nö, er wollte wissen, ob man den Seiteneffekt Synchronisierung nur> einmal abwarten muß und das kann man bei nur einer Zuweisung.
Threadname sagt es aber anders:
"AVR/C: Bits in Register in einem Schritt löschen und andere setzen"
Peter D. schrieb:> Ich bevorzuge allerdings die Vorrangregeln:
TCCR2B = TCCR2B & ~(1<<WGM22 | 1<<CS21) | 1<<CS22 | 1<<CS20;
So ist es OK.
Marc V. schrieb:> Peter D. schrieb:>> Marc V. schrieb:>>> aber der TO wollte wissen ob das irgendwie in einem>>> Schritt (ein Befehl) zu machen ist.>>>> Nö, er wollte wissen, ob man den Seiteneffekt Synchronisierung nur>> einmal abwarten muß und das kann man bei nur einer Zuweisung.>> Threadname sagt es aber anders:> "AVR/C: Bits in Register in einem Schritt löschen und andere setzen"
Ihr habt beide irgendwie Recht. Mir ging es darum die entsprechenden
Bits in einem Schritt auf die richtigen Werte zu (über)schreiben, um die
Synchronisierung (ASSR-Register prüfen) zu sparen. Vielleicht war das
nicht ganz klar formuliert, aber ich wollte halt nur einen
Schreibvorgang auf das TCCR2B Register durchführen.
Patrick S. schrieb:> aber ich wollte halt nur einen> Schreibvorgang auf das TCCR2B Register durchführen.
Dann mach das doch einfach. Die FOC-Bits wirst du an mit Sicherheit
grenzender Wahrscheinlichkeit nicht benutzen, und von alleine ändern die
sich auch nicht.
Und damit ist
Oliver S. schrieb:> Und damit istTCCR2B = (1<<CS22) | (1<<CS20);> die Lösung deines Problems.
Nein! Es kann nämlich sein, dass WGM22 bzw CS21 zuvor auf 1 gesetzt
waren. Aus diesem Grund mache ich das wie oben geschrieben und damit ist
die Sache erledigt.
Patrick S. schrieb:> Nein! Es kann nämlich sein, dass WGM22 bzw CS21 zuvor auf 1 gesetzt> waren. Aus diesem Grund mache ich das wie oben geschrieben und damit ist> die Sache erledigt.
Na ja, du kannst machen, was du willst. Sinnvoll ist es in diesem Fall
nicht.
Patrick S. schrieb:> ich möchte gerne auf einem ATmega 328p im Register TCCR2B die Bits CS22> und CS20 setzen und die Bits CS21 und WGM22 löschen.
Oliver
Oliver S. schrieb:> Na ja, du kannst machen, was du willst. Sinnvoll ist es in diesem Fall> nicht.
Selbstverständlich ist das sinnvoll. CS20 = CS21 = CS22 = 1 haben
natürlich eine ganz andere Bedeutung als CS20 = CS22 = 1, CS21 = 0
Analog für die WGM Bits.
Natürlich.
Oliver S. schrieb:> TCCR2B = (1<<CS22) | (1<<CS20);
Das ist eine einfache Zuweisung, danach sind alle Bits in dem Register
so, wie du sie habe willst. CS22 und CS20 sind 1, alle andern Bits in
dem Register sind 0. Die FOC-Bits werden dabei zwar mit 0
überschrieben, das stört aber nicht.
Oliver
Oliver S. schrieb:> Das ist eine einfache Zuweisung, danach sind alle Bits in dem Register> so, wie du sie habe willst. CS22 und CS20 sind 1, alle andern Bits in> dem Register sind 0. Die FOC-Bits werden dabei zwar mit 0> überschrieben, das stört aber nicht.
Das habe ich auch so gedacht, als ich angefangen habe. Es ist nicht
nur eine schlechte Angewohnheit, es ist sogar eine furchtbare.
Anzunehmen, dass ein bestimmter Register einen bestimmten Wert hat
oder das Überschreiben gewisser bits "nicht stört" ist ganz einfach
dumm, ich kenne kein anderes Wort dafür.
Marc V. schrieb:> Peter D. schrieb:>> TCCR2B = (TCCR2B & ~((1<<WGM22)|(1<<CS21))) | ((1<<CS22|(1<<CS20));>> Das ist nur eine Zuweisung in C, aber mindestens 2 in ASM.
TCCR2B muss in dieser Zeile genau einmal gelesen und einmal geschrieben
werden.
Marc V. schrieb:> Das habe ich auch so gedacht, als ich angefangen habe. Es ist nicht> nur eine schlechte Angewohnheit, es ist sogar eine furchtbare.> Anzunehmen, dass ein bestimmter Register einen bestimmten Wert hat> oder das Überschreiben gewisser bits "nicht stört" ist ganz einfach> dumm, ich kenne kein anderes Wort dafür.
Nun ja, ich bezeichne es als dumm, nicht ins Datenblatt zu schauen, und
eine "one size fürs all" Lösung zu verwesen, die unnötig ist. Gerade bei
diesen Timerkonfigurationsregistern ist es sehr sinnvoll, GENAU das
hineinzuschreiben, was hinein soll, und sonst gar nichts.
Das Register setzt den Takt und die Betriebsart des Timers. Da gibt es
keine "vorher" gesetzten Bits. Da gibt es nur genau einen einzigen Wert,
der da in einem Rutsch hineingeschrieben wird. Und weil das so ist, ist
es guter Programmierstil, das auch genauso ins Programm zu schreiben.
Die FOC-Bits sind extra dafür gemacht, folgenlos mit 0 überschreiben zu
werden.
Es gibt andere Register, da will man einzelne Bits setzen. Die
Fragestellung war aber spezifisch für TCCR2B beim Mega328p, und dafür
ist die schnellste, sicherste und einfachste Lösung, den gewünschten
Wert dort einfach hineinzuschreiben.
Oliver
Rolf M. schrieb:> TCCR2B muss in dieser Zeile genau einmal gelesen und einmal geschrieben> werden.
Wie geht das denn ?
Auf einmal AND 2 bits, OR 2 bits und die übrigen 4 bits unverändert -
das geht nie und nimmer in ASM.
Was in dieser Zeile steht, ist uninteressant - deswegen gibt es auch
höhere Programmiersprachen - wie diese Zeile aber übersetzt wird...
Marc V. schrieb:> Rolf M. schrieb:>> TCCR2B muss in dieser Zeile genau einmal gelesen und einmal geschrieben>> werden.>> Wie geht das denn ?
Ich sehe da kein Problem.
> Auf einmal AND 2 bits, OR 2 bits und die übrigen 4 bits unverändert -> das geht nie und nimmer in ASM.
Ich hab nicht gesagt, dass er alles in einem Schritt berechnet,
lediglich, dass TCCR2B genau einmal gelesen und einmal geschrieben wird.
> Was in dieser Zeile steht, ist uninteressant - deswegen gibt es auch> höhere Programmiersprachen - wie diese Zeile aber übersetzt wird...
Das gilt aber nicht für Variablen, die volatile sind, was auf alle
I/O-Register zutrifft. Bei denen müssen die Zugriffe physikalisch so
stattfinden, wie sie im Code stehen.
Rolf M. schrieb:> Ich hab nicht gesagt, dass er alles in einem Schritt berechnet,> lediglich, dass TCCR2B genau einmal gelesen und einmal geschrieben wird.
LOL.
Und zwei Befehle dazwischen.
Auch bei folgendem Unfug wird TCCR2B genau einmal gelesen und einmal
geschrieben:
1
TCCR2B=((TCCR2B&(TCCR2B<<4))%7)*4;
Wieviele Schritte dazwischen sind, ist eine andere Frage.
Marc V. schrieb:> Rolf M. schrieb:>> Ich hab nicht gesagt, dass er alles in einem Schritt berechnet,>> lediglich, dass TCCR2B genau einmal gelesen und einmal geschrieben wird.>> LOL.> Und zwei Befehle dazwischen.
Was ist daran "LOL"? Natürlich kann er das nicht in einem Schritt
berechnen. Das hat aber doch mit den Zugriffen auf das Register erstmal
nichts zu tun.
> Auch bei folgendem Unfug wird TCCR2B genau einmal gelesen und einmal> geschrieben: TCCR2B = ((TCCR2B & (TCCR2B << 4)) % 7) * 4;
Nein. Es wird zweimal gelesen, da du hingeschrieben hast, dass es
zweimal gelesen werden soll.
> Wieviele Schritte dazwischen sind, ist eine andere Frage.
Richtig.