Forum: Mikrocontroller und Digitale Elektronik Was tut TCCR1A = (1<<PWM11)|(1<<PWM10)|(1<<COM1A1);


von popi (Gast)


Lesenswert?

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
von Μαtthias W. (matthias) Benutzerseite


Lesenswert?


von TheForce (Gast)


Lesenswert?

(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.

von popi (Gast)


Lesenswert?

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

von popi (Gast)


Lesenswert?

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

von Mark H. (haemi)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von popi (Gast)


Lesenswert?

... 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

von Hannes H. (mui)


Lesenswert?

Wow - dafür einen sechs Jahre alten Thread rauskramen...

: Wiederhergestellt durch Moderator
von chef (Gast)


Lesenswert?

einfach Pull ups für PORTB setzen !
dann dürfte dein problem bereinigt sein.

2 lösung Maskiere deinen Ausgang !!

von HildeK (Gast)


Lesenswert?

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.

Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.