Ich habe ein Verständnisproblem in C. Als Elektroniker-Azubi habe ich
von Programmierung nicht so viel Ahnung, ich arbeite mich allerdings
gerade ein.
Ich habe an Pins 0-3 von PortB eines Atmega328 (verbaut auf einem
Arduino)einen Drehcoderschalter, der binär raufzählt. Die anliegende
Binärzahl soll über eine Switch-Case-Anweisung in einen Befehl umgesetz
werden.
Da ich ja nicht den gesamten Port auslesen möchte, sondern nur die
ersten vier Pins, muss ich den Weg über eine Maske gehen, richtig?
Also habe ich geschrieben:
1
switch(PORTB && 0x11110000)
2
3
case 0:
4
...
5
case 1:
6
...
7
...
In dieser Form funktioniert das Programm leider nicht, die Anweisungen
werden nicht ausgeführt.
Kann mir da jemand meinen Fehler aufzeigen?
Viele Grüße
Krümel
PS: Außerdem habe ich noch das Problem, dass Pin1 von PortD (da hängt
auch RX dran) dauerhaft High-Pegel liefert, obwohl er als input
definiert ist. Die serielle Kommunikation ist deaktiviert.
Ich vermute ehrlich gesagt, dass es ein Hardwaredefekt ist (wie auch
immer ich das geschafft habe), aber vielleicht hat ja auch hier jemand
zufällig einen Rat zur Hand =)
Krümel schrieb:> Also habe ich geschrieben:switch(PORTB && 0x11110000)
Sieh Dir mal ganz genau an, was für eine Verknüpfung Du da verwendest.
Und sieh Dir an, was das für eine Zahlenkonstante ist.
Zwei Tips:
&& ist nicht &
C kennt keine binären Konstanten; was Du da geschrieben hast, ist
hexadezimal.
Rufus Τ. Firefly schrieb:> Zwei Tips:>> && ist nicht &>> C kennt keine binären Konstanten; was Du da geschrieben hast, ist> hexadezimal.
Dritter Tip:
PORTx ist nicht dasselbe wie PINx
die idee ist richtig. hast dich nur im zahlensystem vertan. du möchtest
die unteren 4 bits ausmaskieren. dafür musst du 0xF0 schreiben. in binär
waren das deine 11110000. außerdem muss die verundung bitweise erfolgen
also nur ein & und kein && (logisch)... deine abfrage ergibt immer 1
weil außer alle pins vom port sind low
> Da ich ja nicht den gesamten Port auslesen möchte, sondern nur> die ersten vier Pins, muss ich den Weg über eine Maske gehen, richtig?
Die Schlussfolgerung ist grundsätzlich richtig, aber mit der Herleitung
bin ich unzufrieden.
Denn der springende Punkt ist: Du kannst einen Port immer nur als ganzes
auslesen. Alle 8 Bit. Das ist so, weil in C die kleinste Einheit nun mal
ein Byte ist.
Aber: Es steht dir natürlich frei, von diesen 8 Bit diejenigen Bits, die
du nicht benötigst, gezielt auf 0 zu setzen. Genau das machst du mit der
Maske und ab da stimmt dann dein Gedankengang wieder.
Ergo: Die Frage lautet nicht: wie kann ich von einem Port die Bits, die
ich nicht brauche, überhaupt nicht auslesen. Denn daran, dass du alle
auslesen musst, führt kein Weg vorbei (zumindest nicht auf
konzeptioneller C-Ebene). Alle 8 Bit auslesen ist daher obligatorisch
und dieser Punkt steht nicht zur Debatte. Die Frage lautet: Wie kann ich
meine 8 so gelesenen Bit weiterverarbeiten, dass ich nur die mich
interessierenden Bits betrachte?
Ein kleiner aber feiner Unterschied in der Betrachtungsweise.
> PS: Außerdem habe ich noch das Problem, dass Pin1 von PortD (da hängt> auch RX dran) dauerhaft High-Pegel liefert, obwohl er als input> definiert ist.
Wohl, weil du den Pullup aktiviert hast.
PORTx ist nicht dasselb e wie PINx.
Wenn du PINx ausliest, kriegst du den tatsächlichen Zustand des Pins.
Liest du PORTx aus, dann kriegst du Information darüber, ob an diesem
Pin der Pullup Widerstand eingeschaltet ist oder nicht.
Frank schrieb:> du möchtest> die unteren 4 bits ausmaskieren.
Die oberen.
Krümel schrieb:> Ich habe an Pins 0-3 von PortB eines Atmega328 (verbaut auf einem> Arduino)einen Drehcoderschalter, der binär raufzählt.
DrWright schrieb:> uint8_t count = (PINB & 0xF0)>>4;
Ohne die Verschiebung und die Maske genau anders rum.
Seine Encoder hängt ja schon an den Pins 0 bis 3
Klar, es muss 0x0F oder 0b00001111 heißen, was für zwei blöde Fehler ;/
Den Unterschied zwischen PIN und PORT hab ich nun auch raus... Mit PORT
lese ich nur den Zustand des Pullups aus. Alles klar, also Abfrage auf
PINB.
Und zum dritten Punkt: Achso, ich verändere mit der Maske also nicht den
Bereich den ich auslese, sondern ich verunde dann jedes einzelne Bit des
Ports mit meiner "Maske"!
Wunderbar, jetzt läuft das Programm einwandfrei =)
@Karl Heinz
An der Aktivierung des Pullups scheint es nicht zu liegen. Ich habe
gerade extra nochmal
> eingefügt, aber der Pin ist immer noch auf 5V.
Da müsste man jetzt mal den Schaltplan studieren, ob an diesem Pin eine
externe Beschaltung angeschlossen ist.
"The problem is that pin 0 has external on-board wiring to the on-board USB serial converter and even when not using any serial communications or not even wired to the PCs USB, pin 0 has effectivly a 1k ohm pull up resistor wired to the pin. Adding external pull-down resistor just creates a voltage divider situation and will result in not the proper voltage levels to be seen by the input pin. So to use pin 0 as a switch input you should just be able to wire the switch from ground to the input pin. When switch is pushed your digitalRead() will return a zero and a one when not pushed. Try it and see if that doesn't work better for you."
Ok, das war ein Fehler, das Zitat in ein Codefeld zu fügen. Hier nochmal
in leserlich, für die, die es interessiert:
"The problem is that pin 0 has external on-board wiring to the on-board
USB serial converter and even when not using any serial communications
or not even wired to the PCs USB, pin 0 has effectivly a 1k ohm pull up
resistor wired to the pin. Adding external pull-down resistor just
creates a voltage divider situation and will result in not the proper
voltage levels to be seen by the input pin. So to use pin 0 as a switch
input you should just be able to wire the switch from ground to the
input pin. When switch is pushed your digitalRead() will return a zero
and a one when not pushed. Try it and see if that doesn't work better
for you."