C syntaxproblem

Gast #2143929
Lesenswert?

kurze knackige frage:

"  // Alle Pins des Ports B als Ausgang definieren:
  DDRB = 0xff;
  // Pin0 wieder auf Eingang und andere im ursprünglichen Zustand 
belassen:
  DDRB &= ~( 1 << DDB0 );
  // Pin 3 und 4 auf Eingang und andere im ursprünglichen Zustand 
belassen:
  DDRB &= ~( ( 1 << DDB3 ) | ( 1<<DDB4) );
  // Pin 0 und 3 wieder auf Ausgang und andere im ursprünglichen Zustand 
belassen:
  DDRB |= ( 1 << DDB0) | ( 1 << DDB3 );
  // Alle Pins auf Eingang:
  DDRB = 0x00; "

warum wird bei der invertierung &= und bei normalgebrauch |= benutzt?
der rest versteh ich
Gast #2143940
Lesenswert?

Schau dir mal die Bedeutung des bitweisen UND und ODER an.

Wenn du etwas mit 1 veroderst bekommst du definitiv eine 1 wenn du eine 
0 veroderst bleibt der Ursprungszustand des Vergleichsbits erhalten.

Wenn du etwas mit 0 verundest bekommst du definitiv eine 0, wenn du 
etwas mit 1 verundest bleibt der Ursprungszustand erhalten.

Das wird gemacht, wenn "nur bestimmte" Bits verändert werden sollen und 
der Rest innerhalb des Bytes unverändert bleiben soll.
Persönliche Seite #2143948
Lesenswert?

Benni schrieb:
> warum wird bei der invertierung &= und bei normalgebrauch |= benutzt?

Was macht die logische Operation UND, und was macht die logische 
Operation ODER?

>   DDRB &= ~( 1 << DDB0 );

Schreib Dir mal in Form von 8-Bit-Binärzahlen auf, was

- in DDRB steht, bevor die Zeile ausgeführt wird
- was "DDB0" ist
- was 1 << DDB0 ist
- was ~(1 << DDB0) ist

und was DDRB & dieser letzte Wert ist.

Dasselbe wiederholst Du für

>  DDRB |= ( 1 << DDB0) | ( 1 << DDB3 );

- was steht vorher in DDRB?
- was sind DDB0 und DDB1?
- was ist 1 << DDB0?
- was ist 1 << DDB3?
- was ist (1 << DDB0) | (1 << DDB3)?

Und was ergibt DDRB | dieser letzte Wert?
Gast #3813864
Lesenswert?

DDB0 und DDB3 sind Postionen der Datenrichtungsregister und in der 
einzubindenden Systembibliothek avr/io.h ist für diese Bezeichnungen 
DDB3=PINB3=3 und DDB0=PIN0=0 definiert.
DDRB ist die Datenrichtungsregister an Port B, 0 ist für Eingang, 1 ist 
für Ausgang. Das ist ein 8 Bitmuster.

Pin 0 und 3 an Port B als Ausgang definieren:
DDRB |= ((1<<DDB0) | (1<<DDB3))
Pin 0 an Port B als Eingang definieren:
DDRB &= ~( 1 << DDB0 )
Pin 3 an Port B als Ausgang definieren:
DDRB |= 1<<DDB3
Gast #3813922
Lesenswert?

Kaj schrieb:
> Das scheitert schon daran, das man (soweit ich weiss) eine 0 nicht
> shiften kann. ;)

Dann denk nochmal nach. Ergibt das Sinn?
Fragst du eine Variable auf 0 ab, bevor du Bits verschiebst?

In dem zitierten Fall wird es noch nicht mal vom Programm berechnet 
sondern schon vom Kompiler ausgewertet, da konstant.

0b00000000 um x nach y verschoben ist ...?
Gast #3814663
Lesenswert?

Man kann auch 0 schiften aber nach der Verschiebung hat man wiederum 0 
und ein Bitmaske von 0 hat keine Informationen und das ist sinnlos für 
eine Bitoperation.

DDRB &= ~( 1 << DDB0 ) Bit 0 an Port B ist Eingang (Korrekt)

DDRB |= (0 << DDB0 ) ist Blödsinn! (Bit 0 an Port B kann Eingang oder 
Ausgang sein!)

Man muss auch Datenrichtungsregister nicht per Hand definieren z.B.
wenn man schreibt DDRB=0000 1000 (Pin 3 an Port B als Ausgang definiert)
Dadurch gehen die Information von den anderen Pins an Port B verloren 
also Korrekt  ist:
DDRB |= 1<<DDB3 (Pin 3 an Port B als Ausgang definieren)
Pin 3 an Port B als Eingang definieren:
DDRB &= ~( 1 << DDB3 )
Gast #3814673
Lesenswert?

fdast schrieb:
> Man kann auch 0 schiften aber nach der Verschiebung hat man
> wiederum 0
> und ein Bitmaske von 0 hat keine Informationen und das ist sinnlos für
> eine Bitoperation.
Aber manchmal sinnvoll für die Lesbarkeit, um Bits, die 0 bleiben 
sollen, explizit zu benennen:
1
BREAKFAST_CONF = (1 << COFFEE) | (0 << TEA) |
2
    (1 << WHISKEY) | (0 << BEER) |
3
    (1 << CEREAL) | (1 << MILK) |
4
    (0 << BREAD) | (0 << JAM);

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren