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
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) |
"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
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
> 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.
> 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.
Ok, ich denke damit sind meine Fragen beantwortet. Vielen Dank an alle die sich so schnell und gut darum bemüht haben. Markus
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
_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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.