Forum: Mikrocontroller und Digitale Elektronik Tasterabfrage - Frage zum Pinzustand?


von M. G. (ixil96)


Lesenswert?

Hallo,

ich habe eine Frage zur Zeile:
1
if (!(PIND & (1<<PD2)))

Ich lese damit einen Taster am Pin D2 ein. Soweit so gut, aber wie 
funktioniert es genau? Kann mir jemand diese Zeile genau erklären?

Mit
1
DDRD &= (1<<PD2);

setze ich das Bit D2 zuvor auf Eingang.

Mein Taster ist mit einem Pull-Up Widerstand auf High geschaltet.
Ist der Taster offen, habe ich ein High am PD2.
Ist der Taster geschlossen, habe ich ein Low am PD2

von Mike (Gast)


Lesenswert?

m. g. schrieb:
> if (!(PIND & (1<<PD2)))

Mit PIND liest du den Zustand vom ganzen PortD ein.
Mit (1 << PD2) stellst du eine Maske für Bit2 bereit (0b00000100)
Mit (PIND & (1<<PD2)) maskierst du aus dem PortD-Zustand das Taster-Bit
Mit !... invertierst du das Ergebnis (aus "gleich 0" wird "ungleich 0")
Mit if (...) steuerst du deinen Programmablauf

Und in deinem C-Buch oder Tutorial steht ist das nicht unter dem Thema 
Bitmanipulationen beschrieben?

von Karl H. (kbuchegg)


Lesenswert?

m. g. schrieb:
> Hallo,
>
> ich habe eine Frage zur Zeile:
>
>
1
> if (!(PIND & (1<<PD2)))
2
>
>
> Ich lese damit einen Taster am Pin D2 ein. Soweit so gut, aber wie
> funktioniert es genau? Kann mir jemand diese Zeile genau erklären?

Ein ganz normaler binäres Und.

Es hat die Logik-tabelle
1
   A   B    Ergebnis
2
   0   0      0
3
   1   0      0
4
   0   1      0
5
   1   1      1

Das Ergebnis ist also nur dann eine 1, wenn sowohl A als auch B den Wert 
1 haben.

So weit so gut. Das gilt bei 1 Bit.
Jetzt hast du aber vom Port nicht 1 Bit, du kriegst vom Port 8 Stück 
davon.

Diese binäre Und-Operation wird auf alle 8 Bits gleichzeitig angewendet
1
   vom Port     01010011    (das ist die Komponente 'A', 8 mal)
2
   die Maske    00011000    (das ist die Komponente 'B', ebenfalls 8 mal)

und jetzt wendest du die Und-Operation auf alle 8 Spalten getrennt an. 
Jede Spalte für sich
1
   vom Port     01010011    (das ist die Komponente 'A', 8 mal)
2
   die Maske    00011000    (das ist die Komponente 'B', ebenfalls 8 mal)
3
                --------
4
                ||||||||
5
                vvvvvvvv
6
7
                00010000

Das ist interessant. Denn da ist nur eine einzige 1 übrig geblieben. 
Tatsächlich ist es so, wenn man sich die Logik Tabelle mal genau 
ansieht, dann ist das Ergebnis auf jeden Fall dort 0, wo in B eine 0 
auftaucht.
Genau das wird hier ausgenutzt. Wenn ich mal genau diese Spalten im 
Ergebnis markiere, dann steht da
1
   vom Port     01010011    (das ist die Komponente 'A', 8 mal)
2
   die Maske    00011000    (das ist die Komponente 'B', ebenfalls 8 mal)
3
                --------
4
                ||||||||
5
                vvvvvvvv
6
7
                zzz10zzz

d.h. alle mit z markierten Stellen sind im Ergebnis auf jeden Fall 0, 
egal, welcher Wert in der Komponente A war. Bei den beiden übrig 
gebliebenen Spalten, die nicht z sind, hängt es von A ab, ob da jetzt 
eine 1 oder eine 0 auftaucht.

Was du also gemacht hast, ist mit den 1 Bits in der Maske ein "Sieb" 
aufzuspannen, welches dir nur ganz bestimmte Bits aus dem Original 
durchlässt und alles andere gezielt auf 0 setzt.

In deinem Fall, 1<<PD2, lässt das Sieb nur eine einzige Spalte durch. 
Nämlich die an Bitposition 2.
1
      01010011
2
      00000100
3
     ----------
4
      zzzzz0zz

das ergebnis ist deswegen 0, weil im Original auch ein 0 Bit an dieser 
Position war.
bedenkt man jetzt, dass z ja eigentlich als 0 zu lesen ist, dann steht 
da
1
      01010011
2
      00000100
3
     ----------
4
      00000000

und das ist über alle Bits gesehen eine glatte dezimale 0

Wäre das Bit auf 1 gewesen
1
      01010111
2
      00000100
3
     ----------
4
      00000100

dann kommt da etwas ungleich 0 heraus. Welche Zahl das genau ist, ist an 
dieser Stelle nicht wirklich wichtig. Wichtig ist, dass es nicht 0 ist.

Denn jetzt kommt eine C-Eigenart ins Spiel:
1
   if( Ausdruck )

das if interessiert sich nicht für den konkreten Zahlenwert. Für das if 
stellt sich nur die Frage: Ist der angegebene Ausdruck 0 oder ist er 
nicht 0.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Was ich noch vergessen habe:
du musst jetzt natürlich auch noch das Verhalten des ! mit ins Kalkül 
ziehen.
Was macht er?

von M. G. (ixil96)


Lesenswert?

Karl Heinz schrieb:
> Was ich noch vergessen habe:
> du musst jetzt natürlich auch noch das Verhalten des ! mit ins Kalkül
> ziehen.
> Was macht er?

Nun mit dem ! wird negiert. Z.B.: aus

 01010111
 00000100
 ----------
 00000100

wird mit !

 11111011

Richtig?

von Mike (Gast)


Lesenswert?

m. g. schrieb:
> Richtig?

Falsch.
'!' ist ein logischer Operator
http://de.wikibooks.org/wiki/C-Programmierung:_Ausdr%C3%BCcke_und_Operatoren

Mike schrieb:
> Mit !... invertierst du das Ergebnis (aus "gleich 0" wird "ungleich 0")

von Amateur (Gast)


Lesenswert?

>Mit
>DDRD &= (1<<PD2);
>setze ich das Bit D2 zuvor auf Eingang.

... aber nur unter bestimmten Bedingungen (z.B. Sonntags).
An Wochentagen klappt das nicht.

von Josef D. (jogedua)


Lesenswert?

m. g. schrieb:
> Mit
> DDRD &= (1<<PD2);
>
> setze ich das Bit D2 zuvor auf Eingang.

Ganz und gar nicht.
Es setzt alle außer D2 auf Eingang und läßt D2 unverändert.

von Felix S. (pepe)


Lesenswert?

Josef D. schrieb:
> m. g. schrieb:
>> Mit
>> DDRD &= (1<<PD2);
>>
>> setze ich das Bit D2 zuvor auf Eingang.
>
> Ganz und gar nicht.
> Es setzt alle außer D2 auf Eingang und läßt D2 unverändert.


DDRD &= ~(1<<PD2);
setzt den Pin sicher auf Eingang.

DDRD &= (1<<PD2);
klappt bei dir nur, weil das entsprechende Bit in DDRD vorher schon 0 
war.

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.