Ich nochmal,
Also was genau macht denn diese Zeile:
TCCR1A = (1<<PWM11)|(1<<PWM10)|(1<<COM1A1);
Was ich erkennen kann, ist das ir Register TCCR1A bestimmte Bits (hier
PWM11, PWM10 und COM1A1 genannt) gesetzt werden und zwar auf den Wert
1.
Aber warum ODER (|) und was machen diese << Zeichen
Danke
popi
(1<<PWM11) bedeutet, du nimmst eine 1 und verschiebst sie an die Stelle
an der das PWM11-Bit sitzt. PWM11 wird über die .inc-Datei die deinem
Controller entspricht (z.B. m8def.inc für den ATmega8) in eine
Bit-Nummer übersetzt.
Das ganze wird dann mit "oder" verknüpft und dem Register TCCR1A
zugewiesen.
warum schiebe ich den die Bits da rein. Verschieben sich nicht die
anderen, berist vorhandenen?
Warum wird nicht einfach gesetzt ??
Wenn das Register wie folgt aussieht: 0000000
und ich schiebe mit 1<<WGM11 eine 1 rein, dann sieht es doch so aus:
0000010
Wenn ich nun mit 1<<WGM10 noch eine 1 reinschiebe, müsste das dann
nicht so aussehen: 00000101, weil die andere 1 ja auch mitgeschoben
wird ?!
Oder sehe ich das falsch ?
Danke und Grüße
popi
hallo und danke, klingt einleuchtend.
Ich schiebe also nur ein Bit in einer Speicherstelle, wenn man so will,
da wird nicht anderes mirverschoben. Ich setzt also eher Bits.
Und dann die ODER-Verknüfpung... das raffe ich.
Was würde passieren, wenn ich mit 1>>WGM10 schiebe ???
In dem Fall das gleiche, oder ???
Danke und Grüße
popi
Salve,
wie kommst Du denn drauf, daß in dem TCCR1A-Register selbst irgendetwas
geschoben wird? Das ist eine ganz simple Zuweisung, und zwar mit einem
konstanten Wert. Achte auf die Klammersetzung. Es werden jeweils
lediglich die Einsen um den Wert in den Konstanten (WGM..., COM...)
verschoben, bzw. die Einsen mit den entsprechenden Zweierpotenzen
multipliziert.
Der Compiler erkennt, daß es sich bei dem Ergebnis um eine Konstante
handelt und übersetzt das ganze entsprechend als Immediate-Anweisung.
Wie gesagt, es gibt keinerlei Rückbezug auf das Register selbst. Da
wird also gar nix geschoben.
Wenn Du mit >> nach rechts schiebst, wird das Ergebnis Null, da die
Eins ins Nichts geschoben wird, und 0 übrig bleibt, bzw. das
ganzzahlige Ergebnis der Division 1/2 gleich Null ist. Es ist ein
Shift, kein Rotate!
Versuch mal, Dich mit den Grundlagen der Binäroperationen vertraut zu
machen. Das mußt Du unbedingt beherrschen, wenn Du mit µCs arbeiten
willst.
Mark
> warum schiebe ich den die Bits da rein. Verschieben sich nicht> die anderen, berist vorhandenen?>> Warum wird nicht einfach gesetzt ??
Wird es doch letztendlich.
Zu guter letzt wird das Ergebnis des arithmetischen
Ausdrucks dem Port zugewiesen und erst dann werden
die Ports tatsaechlich gesetzt.
TCCR1A = (1<<PWM11)|(1<<PWM10)|(1<<COM1A1);
Ich nehme jetzt mal ein paar Zahlenwerte an, da ich die
korrekten Werte fuer PWM11, PWM10 und COM1A1 nicht kenne
PWM11 7
PWM10 6
COM1A1 2
das bedeutet also, wenn Du PWM11, PWM10 und COM1A1 haben willst,
dann brauchst Du ein Byte in dem bit 7, Bit6 und Bit2 gesetzt
sind:
1100 0100
Natuerlich kannst Du Dir den Zahlenwert dafuer ausrechnen. Aber
dann kann keiner mehr direkt erkennen wie dieser Zahlenwert
auszusehen hat. Daher die obige Schreibweise
1 << PWM11 oder was gleichbedeutend ist, da PWM11 ja 7 ist
1 << 7
beduetet: Nimm eine 1 und schieb sie 7 mal nach links
0000 0001 da ist die 1, und jetzt schieben wir sie
7 mal nach links
0000 0010 1 mal
0000 0100 2 mal
0000 1000 3 mal
0001 0000 4 mal
0010 0000 5 mal
0100 0000 6 mal
1000 0000 7 mal
perfekt. Das ist eine Bitmakse in der tatsaechlich Bit 7 gesetzt ist
(und sonst nichts)
1 << PWM11 ergibt also binaer 1000 0000
1 << PWM10 (PWM10 war 6) 0100 0000
1 << COM1A1 (COM1A1 war 2) 0000 0100
alles was jetzt noch bleibt ist, diese 3 individuellen Bit-
Masken miteinander zu kombinieren, sodass eine einzige
Maske enthaelt, die ueberall dort eine 1 hat, wo irgendeine
der 3 Einzelmasken eine 1 hat.
Dazu nimmt man eine Oder-Verknuepfung. Denn Oder ist ja:
entweder A oder B oder beide. In Tabellenform
EIngangssignal A Eingangssignal B Ergebnis
0 0 0
1 0 1
0 1 1
1 1 1
Konkret: Wenn man 1000 0000 mit 0100 0000 oder verknuepft:
1000 0000
OR 0100 0000
---------
1100 0000
Im Ergebnis ist genau dort eine 1 wo in einem der beiden Ausgangs-
werte eine 1 war.
Jetz noch dieses Zwischenergebnis mit der 3. Maske 0000 0100
oder verknuepfen
1100 0000
OR 0000 0100
---------
1100 0100
und Du hast genau das Bitmuster das du brauchst um as an den
Port zuzuweisen.
TCCR1A = (1<<PWM11)|(1<<PWM10)|(1<<COM1A1);
Der Kenner liest das als: TCCR1A wird programmiert mit einem
Bitmuster in dem das Bit PWM11, PWM10 und COM1A1 gesetzt sind.
... das war eine echt gute Erklärung!!!!
Vielen Dank für die Schreibmühe.
So langsam löst sich der Nebel ;o)
Ich werd mal das gelernte Anwenden und im Simulator betrachten.
Nochmals vielen Dank!
Grüße
popi
Karl Heinz Buchegger schrieb:> ....> TCCR1A = (1<<PWM11)|(1<<PWM10)|(1<<COM1A1);
Das war wirklich eine anfängertaugliche Erklärung von dir - großes Lob!
Da solche Ausdrücke recht häufig in der Form
TCCR1A |= (1<<PWM11)|(1<<PWM10)|(1<<COM1A1);
^
auftreten, wäre noch zu vervollständigen, dass in dem Fall zuerst das
Register TCCR1A gelesen wird, dann die drei neuen Bits gesetzt und
wieder zurückgeschrieben werden. Wesentlicher Unterschied: es bleiben
die bereits an anderer Stelle des Registers gesetzten Bits unverändert!
Und zur weiteren Vervollständigung, z.B. der Ausdruck:
TCCR1A &= ~( (1<<PWM11)|(1<<PWM10) );
Hier werden die beiden Bits PWM11 und PWM10 wieder gelöscht.
Zunächst wird wieder ein Bitmuster, wie von Karl-Heinz Buchegger schön
beschrieben, zusammengesetzt (nach seinem Beispiel wäre es dann 1100
0000), anschließend durch die Tilde (~) invertiert (zu 0011 1111) und
dann mit dem zurückgelesenen TCCR1A AND-verknüpft.
Dort stand ja 1100 0100, und AND mit 0011 1111 ergibt 0000 0100. Es
bleibt also in dem Beispiel nur noch COM1A1 gesetzt.