mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Frage zu Bitoperatoren in C (AVR)


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: O. A. (sokrates1989)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

was bedeutet das (1<<PB2) ?

PB steht wohl für PortB.. Muss man das dem MC noch mitteilen oder weiß 
der das.



if (PINB & (1<<2)||(PINB & (1<<3)))

wenn ich soetwas habe, soll das bedeuten wenn "PinB2 = 1" oder "PinB3 = 
1"
dann wäre die Bedingung erfüllt?

Und wäre dann (0<<PB2) = PortB2 = 0?

Danke.

Autor: Olly T. (twinpeaks)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
O. A. schrieb:

> was bedeutet das (1<<PB2) ?

PB2 ist irgendwo in einem AVR-spezifischen Headerfile als 2 definiert.
Damit bedeutet das '1 um 2 Bits nach links geschoben' und soll als 
Bitmaske für PortB Bit 2 stehen. Kann man auch als 0x04 schreiben oder 
00000100 binär (wobei das kein Standard-C ist).


> PB steht wohl für PortB.. Muss man das dem MC noch mitteilen oder weiß
> der das.

Das muss man dem C-Compiler mitteilen, i.d.R. durch inkludieren einer 
passenden Headerdatei. Das hat alles schon einmal jemand definiert.



> if (PINB & (1<<2)||(PINB & (1<<3)))
>
> wenn ich soetwas habe, soll das bedeuten wenn "PinB2 = 1" oder "PinB3 =
> 1"
> dann wäre die Bedingung erfüllt?

Ja.



> Und wäre dann (0<<PB2) = PortB2 = 0?

Nein.

if (PINB & (1<<2)) ist die Kurzform für
if ((PINB & (1<<2)) != 0)


Das Inverse wäre dann
if ((PINB & (1<<2)) == 0)
oder
if (!(PINB & (1<<2)))

Autor: foobar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Das Inverse wäre dann
> if (PINB & (1<<2)) == 0)
> oder
> if (!(PINB & (1<<2)))
  oder
  if (~PINB & (1<<2))

Autor: Wolfgang (Gast)
Datum:

Bewertung
-2 lesenswert
nicht lesenswert
O. A. schrieb:
> PB steht wohl für PortB.. Muss man das dem MC noch mitteilen oder weiß
> der das.

Nein, das "PB" ist dabei völlig bedeutungslos. Entscheiden ist die 2 und 
die steht für das zweite Bit (irgendeines Bytes, das kann genauso Port C 
sein).

Autor: Arduino Fanboy D. (ufuf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wolfgang schrieb:
> Nein, das "PB" ist dabei völlig bedeutungslos. Entscheiden ist die 2 und
> die steht für das zweite Bit (irgendeines Bytes, das kann genauso Port C
> sein).
Das ist nicht ganz richtig!
Ein bisschen Sorgfalt kann auch dort nicht schaden!

Beispiel:
Beim ATMega328P ist PC7 nicht definiert.
PB7 dagegen existiert.

Es ist also nicht immer bedeutungslos, ob B oder C.

Autor: Christian H. (netzwanze) Benutzerseite
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Arduino F. schrieb:
> Es ist also nicht immer bedeutungslos, ob B oder C.

Da PB2 = PC2 = 2, ist es im Prinzip egal, was man verwendet.
Nur der geneigte Leser könnte darüber stolpern. Dem Compiler und dem 
Prozessor ist es egal.

Autor: Arduino Fanboy D. (ufuf)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Christian H. schrieb:
> Da PB2 = PC2 = 2, ist es im Prinzip egal, was man verwendet.
Auch du sprichst über die Implementierung!

Bitte nutze und verbreite die Schnittstelle.
(du selber musst dich ja nicht daran halten, auf deinem Basteltisch)

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arduino F. schrieb:
> Das ist nicht ganz richtig!

Was ist  daran nicht richtig?

Welche Bedeutung hat denn das "PB" deiner Meinung, außer dass es ein 
Namensteil ist, der genauso gut auch MEINPORTBIT heißen könnte

> Beim ATMega328P ist PC7 nicht definiert.
> PB7 dagegen existiert.

Da kommt man hinter, spätestens wenn der Compiler meckert. Nicht 
definierte Zeichenketten zu verwenden, bringt natürlich nichts.

Trotztdem verbirgt sich sowohl hinter PB6 als auch hinter PC6 die Zahl 
6, vorausgesetzt es gibt beide in der betreffenden Prozessordefinition.

Autor: Arduino Fanboy D. (ufuf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wolfgang schrieb:
> Welche Bedeutung hat denn das "PB" deiner Meinung,
>....
> Da kommt man hinter, spätestens wenn der Compiler meckert.

Genau!
Das hast du gut erkannt.
Und darum sollte man auch die richtigen Bezeichner verwenden, damit der 
Compiler eine Chance hat.

Hier mal ein schlechtes Beispiel:
PORTC |= (1<<PB7)
Der Kompiler ist still!

So musses:
PORTC |= (1<<PC7)
Der Kompiler schreit

Wolfgang schrieb:
> außer dass es ein
> Namensteil ist, der genauso gut auch MEINPORTBIT heißen könnte
Zuhause kannst du alles so nennen, wie du willst.
Aber die Verwendung von PB7 oder auch PB2 sind feste Konventionen.

: Bearbeitet durch User
Autor: Axel S. (a-za-z0-9)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian H. schrieb:
> Arduino F. schrieb:
>> Es ist also nicht immer bedeutungslos, ob B oder C.
>
> Da PB2 = PC2 = 2, ist es im Prinzip egal, was man verwendet.

Es ist nur in diesem speziellen Fall egal. Weil bei Atmel netterweise 
die Numerierung von Pins und Bits in den Steuerregistern gleich ist.

Wolfgang schrieb:
> Welche Bedeutung hat denn das "PB" deiner Meinung, außer dass es ein
> Namensteil ist, der genauso gut auch MEINPORTBIT heißen könnte

Genau das ist der wichtige Teil. Genau deswegen verwendet man sprechende 
Bezeichner für Makros (wie hier) oder Variablen (anderswo). PB2 ist die 
Nummer des Steuerbits für den Pin mit dem Namen PB2. Und weil man 
entsprechende Makros für die Steuerbits aller Pins hat, muß und will 
man sich gar nicht mehr damit auseinandersetzen, ob PB2 und PC2 am Ende 
zur gleichen Nummer werden.

Wenn man den Pin PB2 in DDRB/PINB/PORTB anspricht, verwendet man einfach 
das PB2 Makro und fertig. Das ist einfach (lesbar) und selbsterklärend. 
Zugegeben, bei der sehr regulären Anordung der IO-Pins scheint das etwas 
überzogen, aber bei anderen Steuerbits (z.B. beim UART) wird es sofort 
klar, warum man die (und genau nur die) Makros aus den Headerfiles 
nehmen will.

Autor: Heiko L. (zer0)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Axel S. schrieb:
> Und weil man
> entsprechende Makros für die Steuerbits aller Pins hat, muß und will
> man sich gar nicht mehr damit auseinandersetzen, ob PB2 und PC2 am Ende
> zur gleichen Nummer werden.

Andererseits glaube ich kaum, dass jemand ein
PORTD = 0x11;
gegen
PORTD = (1<<PORTD5) | (1<<PORTD1)
austauschen würde. Oder hat wer für sowas einen entsprechenden "switch" 
Verteiler? :D

: Bearbeitet durch User
Autor: Arduino Fanboy D. (ufuf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heiko L. schrieb:
> gegenPORTD = (1<<PORTD5) | (1<<PORTD1)
Das haut dir der Kompiler um die Ohren

Autor: Heiko L. (zer0)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arduino F. schrieb:
> Heiko L. schrieb:
>> gegenPORTD = (1<<PORTD5) | (1<<PORTD1)
> Das haut dir der Kompiler um die Ohren

Aber den Gedanken hast du verstanden?

Autor: Arduino Fanboy D. (ufuf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein!

Korrektur!

>PORTD = (1<<PORTD5) | (1<<PORTD1)
kompiliert bei mir sehr wohl
Also nix "um die Ohren"

: Bearbeitet durch User
Autor: Felix P. (fixxl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heiko L. schrieb:
> Andererseits glaube ich kaum, dass jemand ein PORTD = 0x11;
>
> gegen PORTD = (1<<PORTD5) | (1<<PORTD1)
>
> austauschen würde

Das wäre nicht gut, denn PORTD = 0x11 setzt PD4 und PD0, nicht PD5 und 
PD1.

: Bearbeitet durch User
Autor: Heiko L. (zer0)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Felix P. schrieb:
> Heiko L. schrieb:
>> Andererseits glaube ich kaum, dass jemand ein PORTD = 0x11;
>>
>> gegen PORTD = (1<<PORTD5) | (1<<PORTD1)
>>
>> austauschen würde
>
> Das wäre nicht gut, denn PORTD = 0x11 setzt PD4 und PD0, nicht PD5 und
> PD1.

Aber sonst würdest du den einbauen?

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Axel S. schrieb:
> Wolfgang schrieb:
>> Welche Bedeutung hat denn das "PB" deiner Meinung, außer dass es ein
>> Namensteil ist, der genauso gut auch MEINPORTBIT heißen könnte
>
> Genau das ist der wichtige Teil. Genau deswegen verwendet man sprechende
> Bezeichner für Makros (wie hier) oder Variablen (anderswo). PB2 ist die
> Nummer des Steuerbits für den Pin mit dem Namen PB2. Und weil man
> entsprechende Makros für die Steuerbits aller Pins hat, muß und /will/
> man sich gar nicht mehr damit auseinandersetzen, ob PB2 und PC2 am Ende
> zur gleichen Nummer werden.

Das Problem ist jedoch, dass man auch
TCCR0A |= (1 << WGM02);
schreiben kann, und der Compiler es übersetzt. Denn TCCR0A ist vom Typ 
volatile uint8_t und (1 << WGM02) hat den Typ int, und das ist implizit 
konvertierbar.

Besser wäre es, wenn TCCR0A einen speziellen Typ hätte und es für die 
Bits des TCCR0A und TCCR0B jeweils auch andere Typen geben würde, die 
dann inkompatibel sind, so dass der obige Code zu einem Compilzeitfehler 
führt.

Das lässt sich mit C aber leider nicht machen (mit anderen Sprachen 
schon).

Autor: O. A. (sokrates1989)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habe noch eine Frage.

was bedeutet "==", entspricht das in Assembler etwa "cpi" ?

Das heißt wenn zwei Ausdrücke gleich sind, wird das Z-Flag gesetzt?

Und was ist bedeutet "&=~"

Portb &=~ (1<<PB7)

wobei "~" eine bitweise negation ist. aber in Zusammenhang mit dem dem 
Gleich und "&"?

Autor: Arduino Fanboy D. (ufuf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
O. A. schrieb:
> wobei "~" eine bitweise negation ist. aber in Zusammenhang mit dem dem
> Gleich und "&"?
Auch dort!

> Portb &=~ (1<<PB7)


 (1<<PB7) == 0b10000000
~ 0b10000000 == 0b01111111

PORTB = PORTB & 0b01111111;

Autor: dummschwaetzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
lösche Bit7

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Axel S. schrieb:
> Wenn man den Pin PB2 in DDRB/PINB/PORTB anspricht, verwendet man einfach
> das PB2 Makro und fertig.

Eigentlich gibt es für die Nutzung mit dem PIN-Register den Namen PINB2 
und für das DDRB-Register den Namen DDB2. Denn so heißen diese Bits auch 
im Datenblatt des Prozessors.

Autor: foobar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Und was ist bedeutet "&=~"
>
> Portb &=~ (1<<PB7)

Das sind zwei Operatoren, &= und ~, nur ohne Leerstellen direkt 
hintereinander geschrieben. Etwas anders formatiert:

Portb &= ~(1<<PB7)

Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
foobar schrieb:
> Etwas anders formatiert:
> Portb &= ~(1<<PB7)
Und etwas ganz ausgeschrieben dann:
Portb = Portb & ~(1<<PB7);
In Worten: lese Portb, lösche im gelesenen Wert das Bit 7 durch verUNDen 
mit dem invertierten Wert von 1000000 und schreibe das Ergebnis wieder 
zurück an Portb

: Bearbeitet durch Moderator

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.