Forum: Mikrocontroller und Digitale Elektronik Halben Port in "switch" auslesen


von Krümel (Gast)


Lesenswert?

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 =)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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

von Frank (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

> 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.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

> 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.

von Ralf G. (ralg)


Lesenswert?

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.

von DrWright (Gast)


Lesenswert?

1
uint8_t count = (PINB & 0xF0)>>4;
2
3
switch(count)
4
{
5
    case 1:
6
    .
7
    .
8
    .

Das bisher keiner erwähnt hat das er schieben muss wundert mich.

von Karl H. (kbuchegg)


Lesenswert?

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

: Bearbeitet durch User
von Krümel (Gast)


Lesenswert?

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"!

von Krümel (Gast)


Lesenswert?

Wunderbar, jetzt läuft das Programm einwandfrei =)

@Karl Heinz
An der Aktivierung des Pullups scheint es nicht zu liegen. Ich habe 
gerade extra nochmal
1
PORTD &= ~(1<<0);
eingefügt, aber der Pin ist immer noch auf 5V.

von Karl H. (kbuchegg)


Lesenswert?

Krümel schrieb:

> gerade extra nochmal
>
1
> PORTD &= ~(1<<0);
2
>
> 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.

von Krümel (Gast)


Lesenswert?

Aha, tatsächlich. Forumsauszug:
1
"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."
Nagut, dann eben so.

von Krümel (Gast)


Lesenswert?

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."

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.