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
:
Gesperrt durch Moderator
(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
Wow - dafür einen sechs Jahre alten Thread rauskramen...
:
Wiederhergestellt durch Moderator
einfach Pull ups für PORTB setzen ! dann dürfte dein problem bereinigt sein. 2 lösung Maskiere deinen Ausgang !!
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.