PD3 kommt von einem ordinären
#define PD3 3
überall wo also PD3 steht, ersetzt der Präprozessor
diesen Text 'PD3' mit '3'
damit wird 1 << PD3
zu 1 << 3
und das macht: nimm eine 1 und schieb diese 1 binär dreimal
nach links. Aus 0b00000001 wird also 0b00001000
A |= B
ist die Kurzform für A = A | B
wobei | eine ODER Verknüpfung darstellt. Im Gegensatz zu
|| wird diese aber auf Bitebene durchgeführt, dh. die
gleichwertigen Bits der beiden Partner werden miteinander
ODER-Verknüpft.
Du weist schon:
A B | A | B
-----------+---------
0 0 | 0
1 0 | 1
0 1 | 1
1 1 | 1
In dieser Tabelle ist im Ergebnis genau dann eine 1, wenn
entweder A ODER B ODER Beide 1 waren. Und genau das will
man hier.
Wenn ich
PORTD = PORTD | 0b00001000;
mache, dann wird an die Bitposition 3 auf jeden Fall eine 1
gesetzt, gleichgültig was vorher in PORTD stand. (Die anderen
Bits bleiben so wie sie sind. Schau in die Tabelle: Wenn B 0
ist, dann ist das Ergebnis identisch mit dem Zustand von A)
---------------------------------
PORTD &= ~( 1 << PD3 );
~ macht eine binäre Negation. D.h. alle Bits werden umgedreht.
aus 0b00001000 wird also 0b11110111
A &= B ist wieder eine Kurzform. Diesmal für A = A & B
und das & steht für binäres UND
A B | A&B
----------+------
0 0 | 0
1 0 | 0
0 1 | 0
1 1 | 1
Das Ergebnis ist genau dann 1, wenn A UND B 1 waren.
Schau dir die Tabelle genauer an. In den Zeilen in
denen B 0 ist, ist das Ergebnis auf jeden Fall 0.
In den Zeilen in denen B einen Wert von 1 hat, ist
der Ergebnis identisch mit dem Zustand von A.
Jetzt sollte schon klar sein, was
PORTD = PORTD & 0b11110111
macht. Überall dort wo in der Maske 0b11110111 eine 1
steht, ist das Ergebnis identisch mit PORTD an dieser
Bitposition. Überall dort wo in der Maske eine 0 steht,
wird das betreffende Bit im Ergebnis auf jeden Fall auf
0 gesetzt.