Forum: Compiler & IDEs beginne mit der c programmierung


von markus (Gast)


Lesenswert?

Hallo,
ich fange gerade an für ein Schulprojekt einen AVR zu programmieren. Nun 
ja es klappt eigentlich ganz gut, nur hätte ich da eine Frage zum 
Setzen/Löschen von Bits.
Ich habe da mal was aus dem Tutorial übernommen, kann es aber nicht so 
richtig verstehen.

PORTB=(1<<PB0)|(1<<PB1); dies setzt mir PB0/1 ohne das ganze Register zu 
verändern ?
PORT &= ~(1<<PB2); so kann ich den PB2 löschen, ohne den ganzen Port zu 
manipulieren ?
Was bedeutet das den "ausgeschrieben" dieses | und <<
Kann man das ganze auch in eine Zeile schreiben ?

Vielen Danke für die Hilfe

Markus

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

markus wrote:

> PORTB=(1<<PB0)|(1<<PB1); dies setzt mir PB0/1 ohne das ganze
> Register zu verändern ?

Nein.  Es setzt das Register ausschließlich auf Bits 0 und 1 (also
0x03).  Alle anderen Bits werden gelöscht.

> PORT &= ~(1<<PB2); so kann ich den PB2 löschen, ohne den ganzen Port
> zu manipulieren ?

Ja.

> Was bedeutet das den "ausgeschrieben" dieses | und <<

| ist ein bitweises ODER, das Ergebnis ist also sowas wie die
,,Bitsumme'': alle Bits, die in einem der beiden Operanden gesetzt
waren, werden auch im Ergebnis gesetzt.

& ist ein bitweises UND, im Ergebnis werden nur die Bits gesetzt, die
in beiden Operanden gesetzt sind.  Anders gesagt, es werden alle Bits
gelöscht, die in einem der beiden Operanden gelöscht sind (das erklärt
die Komplementär-Funktion zum ODER).

<< ist der Linkschiebe-Operator.  Wenn man eine 1 um n bits nach links
schiebt, erhält man eine Zahl, in der das n-te Bit (Zählung beginnt
bei 0) gesetzt ist.  Man wandelt eine Bitnummer damit in eine Bitmaske
um.

Denk dran, dass in C die Schreibweise "foo #= bar" eine Kurzform für
"foo = foo # bar" ist, wobei # einer der Operatoren +, -, *, /, %, &,
|, oder ^ sein kann.  (Ich hoffe, ich habe keinen vergessen. ;-)
1
PORTB &= ~(1 << PB2)
ist also weiter nichts als
1
PORTB = PORTB & ~(1 << PB2)

  

von Stefan (Gast)


Lesenswert?

"PORTB=(1<<PB0)|(1<<PB1); dies setzt mir PB0/1 ohne das ganze Register 
zu
verändern?"

Nein. PORTB wird komplett neu gesetzt (=). Und zwar mit einer um PB0-mal 
nach links geshifteten 1 (<<) logisch ODER verknüpft mit einer um 
PB1-mal nach links geshifteten 1.

"PORT &= ~(1<<PB2); so kann ich den PB2 löschen, ohne den ganzen Port zu
manipulieren?"

Ja. PORT wird mit dem alten Inhalt von PORT verundet (&=). Und zwar um 
das komplementäre (~) einer um PB2-mal nach links geshifteten 1 (<<).

Z.B. PB2 = 2
1               = 0b00000001
1<<PB2          = 0b00000100
~(1<<PB2)       = 0b11111011
PORT            = 0b11111111
PORT&=~(1<<PB2) = 0b11111011

von markus (Gast)


Lesenswert?

Hallo Herr Wunsch,
oh , dann muss ich also
PORTB|=(1<<PB0)|(1<<PB1);
schreiben wenn ich nur PB0/1 verändern möchte ?

Danke

Markus

von johnny.m (Gast)


Lesenswert?

> PORTB=(1<<PB0)|(1<<PB1); dies setzt mir PB0/1 ohne das ganze Register zu
> verändern ?

Was Du meinst ist
1
PORTB |= (1<<PB0) | (1<<PB1);
Wie Jörg schon gesagt hat, wird in jedem der beiden Klammer-Ausdrücke 
eine binäre "1" (bei 8 Bit "00000001") um "PB0" bzw. "PB1" nach links 
geschoben. "PB0" und "PB1" sind in der Header-Datei definiert als
1
#define PB0 0
2
#define PB1 1
Also wird aus "1 << PB0" ein "1 << 0", d.h. in Binärschreibweise 
"00000001". Analog für PB1: "1 << 1" entspricht "00000010", also die "1" 
um eine Stelle nach links geschoben.

Die beiden Ausdrücke kann man jetzt bitweise verODERn:
  00000001
 |00000010
 ---------
  00000011
In dem Ausdruck rechts vom "=" sind jetzt die beiden letzten Bits (lfd. 
Nr. 0 und 1) gesetzt. Wenn man das ganze jetzt mit PORTB verODERt, 
werden die beiden Bits, die in der Maske (also dem (konstanten) Ausdruck 
rechts vom "=") gesetzt sind, in PORTB gesetzt und die anderen Bits in 
PORTB bleiben unabhängig von ihrem Ausgangswert unverändert. Da der 
Ausdruck rechts vom "=" konstant und zur Compilezeit bekannt ist, macht 
der Compiler aus
1
PORTB |= (1<<PB0) | (1<<PB1);
ein einfaches
1
PORTB |= 0x03;
wobei "0x03" auch binär als "0b00000011" geschrieben werden kann.

Die Schreibweise mit "<<" dient der besseren Lesbarkeit des Codes. Im 
Prinzip könnte man auch direkt die binäre oder hexadezimale Bitmaske 
hinschreiben, was zumindest bei Portregistern zu keinem großartigen 
Informationsverlust führt. Bei anderen I/O-Registern hingegen ist eine 
reine Zahlenangabe für eine Bitmaske nicht gut lesbar, da man nicht 
sieht, welches Bit da überhaupt gesetzt wird und man erst im Datenblatt 
nachsehen muss, welches Bit an welcher Position im Register steht.

von Karl heinz B. (kbucheg)


Lesenswert?

> oh , dann muss ich also
> PORTB|=(1<<PB0)|(1<<PB1);
> schreiben wenn ich nur PB0/1 verändern möchte ?

Ja das stimmt.

Aber gewöhn dir bitte an, ein bischen mit Leerzeichen
deinen Code zu formatieren.

  PORTB |= (1<<PB0) | (1<<PB1);

ist dasselbe, nur durch die Verwendung von Leerezeichen
so umformatiert, dass man auch beim schnellen Hinschauen
sehen kann, was da passiert. Zum einen sticht das |=
besser heraus (und du hast schon gesehen, dass es da
einen wichtigen Unterschied zu = alleine gibt), zum
anderen ist auch das | im rechten Teil der Zuweisung
durchaus etwas was wichtig ist.


von markus (Gast)


Lesenswert?

Ok,
ich denke damit sind meine Fragen beantwortet.
Vielen Dank an alle die sich so schnell und gut darum bemüht haben.

Markus

von Armel (Gast)


Lesenswert?

hallo,
ich möchte gern wissen, wie ich die Binaire darstellung von Ziffer oder 
Zahlen aus den Bildschirm ausgeben kann. Ich Programmiere momentan in C 
und würde es gern wissen. Ich man könnte es einfach tun ohne die Zahl 
immer durch 2 zu dividieren wie auf dem Papier.
Danke für die Hilfe.
Armel

von Karl heinz B. (kbucheg)


Lesenswert?

_itoa() könnte das.
Schau dir die Doku zur Funktion mal genau an und
achte auf den letzten Parameter.

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.