Forum: Mikrocontroller und Digitale Elektronik Frage zu AVR-C


von O. A. (sokrates1989)


Angehängte Dateien:

Lesenswert?

Hallo,

Was beduetet das "&" ...und was bedeutet das "|" vor dem "="  ??


PORTB |= (1<<1);
                PORTB &= 0x02;

Also prinzipiell ist mir klar dass es ein "oder" bzw. ein "und" ist. 
Aber welche Funktion hat es in diesem Fall?

von Karl der Käfer (Gast)


Lesenswert?

O. A. schrieb:
> Hallo,
>
> Was beduetet das "&" ...und was bedeutet das "|" vor dem "="  ??
>
> PORTB |= (1<<1);
>                 PORTB &= 0x02;
>
> Also prinzipiell ist mir klar dass es ein "oder" bzw. ein "und" ist.
> Aber welche Funktion hat es in diesem Fall?
1
PORTB &= (1<<1);
ist nur eine andere (verkürzte) Schreibweise für:
1
PORTB = PORTB & (1<<1);

Genauso verhält es sich mit dem "Oder"

von Wolfgang (Gast)


Lesenswert?

O. A. schrieb:
> Aber welche Funktion hat es in diesem Fall?

Die gleich, wie in jedem anderen C (-> Assignment Operators)
https://www.tutorialspoint.com/cprogramming/c_operators.htm

von Fabian H. (heisenberg_px)


Lesenswert?

Hallo O. A.

PORTB |= (1<<1);

ist dasselbe wie

PORTB = PORTB | (1<<1);

oder

PORTB = PORTB | 0b000000001

Das heißt soviel das das erste Bit im PORTB gesetzt wird.

|, & und ^ sind BITWEISE Verknüpfungen!!

von O. A. (sokrates1989)


Lesenswert?

Karl der Käfer schrieb:
>
1
> PORTB &= (1<<1);
2
>
> ist nur eine andere (verkürzte) Schreibweise für:
>
1
> PORTB = PORTB & (1<<1);
2
>
>
> Genauso verhält es sich mit dem "Oder"

Es geht ja darum einen Ausgang anzusteuern.
Das kann man doch auch so machen.

PORTC = (1<<1);

wozu noch ein &, bzw |....

von Jim M. (turboj)


Lesenswert?

O. A. schrieb:
> Aber welche Funktion hat es in diesem Fall?

Es soll Dir veranschaulichen dass Du mal ein gutes C-Buch lesen 
solltest. Denn diese relativ alte Sprache ist offensichtlich alles 
andere als selbsterklärend - ohne ein Buch wie den K&R sieht man keine 
Sonne.

Das Beispiel sind übrigens relativ banale Bitmanipulationen...

von Karl M. (Gast)


Lesenswert?

O. A. schrieb:
> Es geht ja darum einen Ausgang anzusteuern.
> Das kann man doch auch so machen.
>
> PORTC = (1<<1);
>
> wozu noch ein &, bzw |....

Nun so ein 8Bit Port hat 8 unterschiedliche Zustände, das sind die 
einzelnen Pin, die man so alle gleichzeitig verändert.
Mit ODER ist in diesem Beispiel nur eins betroffen mit UND ensprechen 
sieben.

von Karl der Käfer (Gast)


Lesenswert?

O. A. schrieb:
> Es geht ja darum einen Ausgang anzusteuern.
> Das kann man doch auch so machen.
>
> PORTC = (1<<1);
>
> wozu noch ein &, bzw |....

Weil bei dieser Schreibweise der gesamte Port C auf 0 gesetzt wird außer 
dem einen Bit. Bei der Schreibweise |= wird nur das eine Bit auf 1 
gesetzt und alle anderen unberührt gelassen.

von Fabian H. (heisenberg_px)


Lesenswert?

Da kommt im Register dann das raus:


   X X X X X X X
 | 0 0 0 0 0 0 1
 = X X X X X X 1


Gibt's auch auf Youtube gute Videos.

von Wolfgang (Gast)


Lesenswert?

Fabian H. schrieb:
> PORTB |= (1<<1);
> ist dasselbe wie
> ...
> PORTB = PORTB | 0b000000001

Das möchte ich bezweifeln.
1
PORTB = PORTB | 0b00000010
 trifft die Sache wohl besser ;-)

von VIA (Gast)


Lesenswert?

O. A. schrieb:
> wozu noch ein &, bzw |....

https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Ver.C3.A4ndern_von_Registerinhalten


schreibst du:
1
PORTB = (1<<1);

wird das gesamte Register PORTB überschrieben.
Bit 7...1 werden gelöscht, unabhängig ihres Zustandes
und nur das erste Bit (Bit 0, LSB) wird gesetzt.
PORTB hat also nach diesem Befehl den Zustand "0000 0001".


verwendest du stattdessen:
1
PORTB |= (1<<1);

wird nur das erste Bit (LSB) im Register PORTB gesetzt (= 1).
Alle anderen Bits bleiben in diesem Fall unverändert.
PORTB hat also nach diesem Befehl den Zustand "xxxx xxxx1".
(x = Zustand vor Ausführung des Befehls)



bzw. analog dazu:
1
PORTB &= ~(1<<1);

hier wird nur das erste Bit (LSB) im Register PORTB gelöscht (= 0).
Alle anderen Bits bleiben in diesem Fall unverändert.
PORTB hat also nach diesem Befehl den Zustand "xxxx xxxx0".
(x = Zustand vor Ausführung des Befehls)

von Fabian H. (heisenberg_px)


Lesenswert?

Erwischt!! ;)

Sorry hast recht!

von Wolfgang (Gast)


Lesenswert?

Fabian H. schrieb:
> Erwischt!! ;)

Nicht nur dich - alle haben fleißig mit gemacht ;-)

von Karl der Käfer (Gast)


Lesenswert?

VIA schrieb:
> PORTB hat also nach diesem Befehl den Zustand "0000 0001".

0000 0010

Da ist eine Schiebe-Operation drin (1<<1) :-)

von O. A. (sokrates1989)


Lesenswert?

Ok. Danke erstmal.

Das heißt....

1.)------------------------

PORTB |= (1<<1);    (1. Befehl)
PORTB &= 0x02;      (2. Befehl)

Der erste Befehl
Bewirkt zunächst: xxxx xx1x

Der zweite bewirkt
anschließend    : xxxx xx0x

erst an, dann aus...und zwar dasselbe Bit korrekt?

2.)-------------------------

könnte man stattdessen auch schreiben,

PORTB |= (1<<1);
PORTB &= (1<<1);

???? HAt doch die gleiche bedeutung.?


3.)-------------------------

Und abschließend, warum sollte man ein Bit erst an und sofort wieder aus 
machen. Nur ausmachen reicht doch. (Es geht hier um das Einschalten 
einer LEd..)

von Stefan E. (sternst)


Lesenswert?

O. A. schrieb:
> PORTB |= (1<<1);    (1. Befehl)
> PORTB &= 0x02;      (2. Befehl)
>
> Der erste Befehl
> Bewirkt zunächst: xxxx xx1x
>
> Der zweite bewirkt
> anschließend    : xxxx xx0x

Nein, du irrst dich beim zweiten Befehl.

von O. A. (sokrates1989)


Lesenswert?

Stefan E. schrieb:
> Nein, du irrst dich beim zweiten Befehl.

was passiert stattdessen?

von Walter S. (avatar)


Lesenswert?

na eine UND-Verknüpfung:

x & 1 == x
x & 0 == 0

von Sebastian S. (amateur)


Lesenswert?

>> PORTB &= 0x02;      (2. Befehl)
>> was passiert stattdessen?
Bei diesem Befehl werden alle Bits, mit Ausnahme von Bit 1 [7...0] auf 0 
gesetzt.
Bit 1 bleibt dabei unverändert.
Also 000000x0 nach Deiner Schreibweise.

Im Übrigen: Die hier verwendeten Befehle können auch auf beliebige 
Variablen angewendet werden. Es müssen keine Ausgänge sein.

von O. A. (sokrates1989)


Lesenswert?

Sebastian S. schrieb:
>>> PORTB &= 0x02;      (2. Befehl)
>>> was passiert stattdessen?
> Bei diesem Befehl werden alle Bits, mit Ausnahme von Bit 1 [7...0] auf 0
> gesetzt.
> Bit 1 bleibt dabei unverändert.
> Also 000000x0 nach Deiner Schreibweise.
>
> Im Übrigen: Die hier verwendeten Befehle können auch auf beliebige
> Variablen angewendet werden. Es müssen keine Ausgänge sein.

das hieße....

PORTB |= (1<<1);    (1. Befehl)
 PORTB &= 0x02;      (2. Befehl)

 Der erste Befehl
 Bewirkt zunächst: xxxx xx1x

 Der zweite bewirkt
 anschließend    : 0000 0010


Hätte man das dann auch direkt mit einem befehl und zwar

PORTB = (1<<1);

realisieren können oder nicht.

Denn ich zitiere:

VIA schrieb:
> schreibst du:
> PORTB = (1<<1);
> wird das gesamte Register PORTB überschrieben.
> Bit 7...1 werden gelöscht, unabhängig ihres Zustandes
> und nur das erste Bit (Bit 0, LSB) wird gesetzt.
> PORTB hat also nach diesem Befehl den Zustand "0000 0010".

von Dietrich L. (dietrichl)


Lesenswert?

O. A. schrieb:
> PORTB |= (1<<1);    (1. Befehl)
>  PORTB &= 0x02;      (2. Befehl)
>
>  Der erste Befehl
>  Bewirkt zunächst: xxxx xx1x

Ja.

>  Der zweite bewirkt
>  anschließend    : 0000 0010

Nein:                0000 00x0

Aber das hat Sebastian ja schon gesagt:

Sebastian S. schrieb:
> Bit 1 bleibt dabei unverändert.
> Also 000000x0 nach Deiner Schreibweise.

von Stefan E. (sternst)


Lesenswert?

O. A. schrieb:
> Hätte man das dann auch direkt mit einem befehl und zwar
>
> PORTB = (1<<1);
>
> realisieren können oder nicht.

Vom logischen Standpunkt her schon. Aber man schaltet Portpins ja nicht 
zum Spaß, sondern weil man damit die externe Hardware, die da dranhängt, 
steuern will. Und dann kann es einen signifikanten Unterschied machen.

von Holger L. (max5v)


Lesenswert?

Wenn du das Atmelstudio verwendest kannst du dir das Verhalten auch 
direkt anschauen.

Projekt -> 'Name' Properties" unter Tool Simulator auswählen
Debug -> Start Debugging and Break

Rechtsklick auf eine (Globale) Variable und "Add Watch"
oder in der I/O Ansicht den entsprechenden Port auswählen.

Mit "Debug -> Step Into, Step Over" etc. kann man nun die einzelnen 
Schritte nachvollziehen.

von Carl D. (jcw2)


Lesenswert?

O. A. schrieb:
> Ok. Danke erstmal.
>
> Das heißt....
>
> 1.)------------------------
>
> PORTB |= (1<<1);    (1. Befehl)
> PORTB &= 0x02;      (2. Befehl)


2. Ist falsch denn eine AND-Verknüpfung setzt alle Bits auf 0, die nicht 
in beiden Werten 1 sind. Es wird "maskiert" und die Maske hat nur auf 
den 0-zusetzenden Bits eine 0.
1
PORTB &= ~0x02;    //  (2. Befehl)

Die Tilde macht den Unterschied. "bitweises Negieren" im Klartext.

Ob man Bits als Zahl oder geschiftete Eins schreibt? Geschmackssache und 
Aufreger zugleich.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.