Forum: Mikrocontroller und Digitale Elektronik Port einzeln abfragen


von Studiologe (Gast)


Lesenswert?

Guten morgen habe mal ne Frage und zwar kann ich ja mit
PORTD &= ~(1 << PD3);    //PD3 auf high
PORTD &= ~(0 << PD2);    //PD2 auf low
PORTD &= ~(1 << PD1);    //PD1 auf high

einzelne Ports setzten, aber wie kann ich einen vereinzelten Port
abfragen ?
ich kenn das bisher nur mit
if(PORTA == 0xFE)..... bzw. if(PORTA == 0b11111110).....
habe es schon mit
if(PORTA |= ~(1 << PA0)) und if(PORTA &= ~(1 << PA0))
vrsucht, aber beides geht nicht, auch wenn ich anstellle der 1 ne 0
setzte,
Kennt einer von euch die richtige Syntax für den befehl ??
weil mit
if(PORTA == 0xFE)..... bzw. if(PORTA == 0b11111110).....
beziehe ich ja auch immer die anderen anschlüsse eines portes mit
in die bedingung, was ich nicht machen möchte,
klar ich könnte es über ne switch-case bedingung machen, aber das für
jeden port, macht den source code auch nicht übersichtlich (kurz und
knapp sollte er sein ) :) !!

Dank euch

von crazy horse (Gast)


Lesenswert?

auf jeden Fall musst du (PINx...) statt (PORTx..) verwenden.

von Philipp Sªsse (Gast)


Lesenswert?

> PORTD &= ~(1 << PD3);    //PD3 auf high

Eher: PORTD |= (1 << PD3);

> PORTD &= ~(0 << PD2);    //PD2 auf low

Eher: PORTD &= ~(1 << PD2);

> wie kann ich einen vereinzelten Port abfragen ?

Ich glaube, Du solltest Dich erst einmal damit beschäftigen, was die
Befehle, die Du benutzt, wirklich bedeuten:

Du hast einen PortD mit den Bits xxxxxxxx.
Der Klammerausdruck (1 << PD3) setzt das letzte Bit und schiebt es an
die Position der Wahl: 00000001 wird zu 00001000.
Der Operator |= macht nun ein logisches Oder von Port und dem anderen
Byte und schreibt es wieder in den Port.

foo |= bar

ist eine Kurzschreibweise von

foo = foo | bar

D.h. bei PORTB |= (1 << PB3) wird das eine Bit auf jeden Fall gesetzt,
die anderen bleiben, wie sie sind:

  xxxxxxxx
| 00001000
= xxxx1xxx

Zum Zurücksetzen invertiert man mit der Tilde ~ den Ausdruck und macht
dann ein logisches UND:

  xxxxxxxx
& 11110111
= xxxx0xxx

> habe es schon mit
> if(PORTA |= ~(1 << PA0)) und if(PORTA &= ~(1 << PA0))

Vorsicht! |= und &= verändern den Port!

Erst einmal solltest Du Dir sicher sein, über welches Register Du bei
Deinem µC auf Eingangsports zugreift. Beim AVR z.B. wäre das nicht
PORTA, sondern PINA. Die Abfrage wäre also z.B.:

if (PINA & (1 << PA0)) ...

Das einfache '&' bildet nur das logische UND, ohne dabei etwas zu
verändern.

Bitte in Zukunft vor dem blinden Übernehmen von fremdem Code und wildem
Ausprobieren erst mit den übernommenen Sprachkonstrukten beschäftigen!
Sonst funktioniert es vielleicht durch Zufall im Einzelfall und später
läuft man in noch viel größeres Chaos ...

von Studiologe (Gast)


Lesenswert?

Ja klar meinte ja auch PINA, hatte es nur in der Eile hier so falsch
geschrieben,habe es im programm auch mit PINA stehen....
|= (bitor), || (log oder) ... ist mir auch bekannt,nur das mit der ~
war mir neu, super,also
Besten dank

von Studiologe (Gast)


Lesenswert?

Hi,
bin nun endlich zuhause und konnte das mal ausprobieren,
geht aber leider nicht....
habe da noch was anderes gefunden, was aber nur unter CodeVision
funktioniert nicht aber beim programmers notepad, hier mein code
    ......
    //if (PIND & (1 << PD0))
    //if(PIND.0 == 1)
    if(PIND == 0b11111110) //das geht
    {
      if(i == 0)
      ..........
als einzigstes funktioniert if(PIND == 0b11111110) //das geht....
ist ja auch klar, nur leider keines der anderen beispiele....
ich weiss sind für euch echt doof klingende fragen, aber wenn man grad
mal mit uc-proggen angefangen ist, ist man dankbar über jede hilfe die
man bekommt und in diesem forum wird einem ja auch echt gut geholfen,
hab bisher ne ganze menge von euch hier gelernt, also gebt mich nicht
auf :) dann kann ich später auch mal endlich jemandem (neuling)
vielleicht helfen ;)
also wie soll's an der stelle aussehen ?

von Karl H. (kbuchegg)


Lesenswert?

> als einzigstes funktioniert

Logisch.
Ist ja auch ganz was anderes.

    //if (PIND & (1 << PD0))

Wie sieht hier die Maske aus

  1 << PD0

Also: da nehmen wir eine 1           binaer  00000001
      und die wird PD0 mal
      nach links geschoben.
      PD0 hat den Wert 0.
      Also wird 0 mal geschoben.
      Das Ergebnis                   binaer  00000001

  //if(PIND.0 == 1)

Hier wird ganz einfach geprueft ob das Bit 0
im PIND eine 1 ist. Im Grunde ist das ganz genau
dieselbe Abfrage wie   PIND & (1 << PD0).
Auch hier wird geprueft ob Bit 0 eine 1 enthaelt.
Ueber die Maske werden alle anderen Bits definitiv
auf 0 gesetzt (das macht die & Verknuepfung) und
das Endergebnis haengt dann nur noch vom Bit 0 ab.

Das hier

    if(PIND == 0b11111110)

ist aber ganz was anderes. Hier muss Bit 0 eine
0 enthaelten, damit der Vergleich wahr wird.

Wenn letzteres bei Dir geht und Dein Schalter am Bit 0
haengt, dann hast Du ihn gegen Masse geschaltet. Das
heist: Ist der Schalter nicht betaetigt, dann siehst Du
am Pin eine 1. Ist der Schalter betaetigt, dann ist
dort eine 0.

So. Der erste Schritt ist (wie immer) mal dafuer zu
sorgen, dass nur das interessierende Bit uebrig bleibt
und alle anderen Bits auf einen defineirten Wert kommen
(unabhaengig davon ob extern an moeglichen Schaltern
gedreht wurde). D.h. aber auch, wir muessen sie ausmaskieren.
Was Du also brauchst ist eine Moeglichkeit in einem Byte
alle Bits, bis auf das interessierende zu loeschen (auf
0 zu setzen). Ein binaeres UND macht das wunderbar.

   Bei   Wert & Maske

bleiben nur die Bits in 'Wert' heil bei denen an der
korrespondierenden Stelle in 'Maske' eine 1 steht. Dort
wo in 'Maske' eine 0 steht, wird im Endergebnis mit
Sicherheit auch eine 0 auftauchen, egal ob jetzt 'Wert'
an dieser Stelle eine 1 oder eine 0 enthaelt.

D.h.

   PIND & 0b00000001

laesst von PIND nur das Bit 0 uebrig, alle anderen Bits
sind definitiv auf 0 gesetzt. D.h. das Endergebnis dieser
UND Verknuepfung kann nur 0 (wenn Bit 0 gleich 0) oder 1
(Wenn Bit 0 gleich 1 ) ist. Ist Bit 0 gleich 0, dann war
Dein Taster gedrueckt.

Also alles zusammengesetzt

  if( ( PIND & 0b00000001 ) == 0 )
  {
    /* Taster gedrueckt */
  }

Anstatt dieses binaeren Monsters, kann man dann noch
schreiben

  if( ( PIND & ( 1 << PD0 ) ) == 0 )
  {
    /* Taster gedrueckt */
  }

Da ja der Ausdruck  1 << PD0  und  0b00000001
gleichwertig sind.

von Rahul (Gast)


Lesenswert?

(1<<PD0) verschiebt die 1 um PD0 Stellen. Müsste also, sofern PD0 = 0
ist, hinterher so aussehen: 0b00000001
PIND & (1<<PD0) fragt also ab, ob sich eine 1 an der Stelle 0
befindet.

Annahme: PIND = 0b01100100
dann ist PIND & (1<<PD0) = 0b00000000 (bitweise Und-Verknüpfung)
Ergebnis des Vergleichs: 0, also nicht wahr.

Annahme: PIND = 0b01100101
dann ist PIND & (1<<PD0) = 0b00000001
Ergebnis des Vergleichs: 1, somit !=0, also wahr.
mit dem (1<<PDx) maskiert man das x-te Bit eines Bytes aus.
Der Vergleich unter CodeVisio mit PIND.0 == 1 ist eigentlich nichts
anderes, ausser, dass die 1 wirklich nur den Zustand eines Bits
beschreibt, und nicht wie bei AVR-gcc ein komplettes Byte.
Dein Vergleich (PIND == 0b11111110) funktioniert nur, wenn wirklich nur
dieses Bitmuster am PIND anliegt; liegt ein weiteres Bit auf 0 ist er
hinfällig.
Um herauszufinden, ob der angenommene Taster an PIND.0 betätigt ist,
und den Pin auf Masse (log. 0) herunterzieht, muß man ein bißchen
binäre Logik anwenden:
Vorraussetzung: Taster gilt als betätigt, wenn PIND.0==0.
1. Fall:
if (~PIND & (1<<PD0)) ...

2. Fall:
if (!(PIND & ~(1<<PD0))) ...

Vielleicht hilft dir das noch: bei jeder Operation in C wird ein Wert
zurückgegeben. Alle Werte ausser 0 gelten in einer Abfrage als wahr.
So kann man auch ziemlich einfach feststellen, ob irgendwas != 0 ist:
if (x) Aktion für x!=0;
else Aktion für x ==0;
andersherum:
if (!x) Aktion für x == 0;
else Aktion für x!=0;

Schönen Gruß
Rahul
Gruß Rahul

von Studiologe (Gast)


Lesenswert?

Super,
habe es verstanden, besten Dank an Dich Karl Heinz Buchegger.
wirklich gut und ausführlich erklärt, vielen vielen Dank !!!
Das mit den Tatsern an Masse oder +5V wusste ich auch nicht, aber ist
ja logisch, das dann jedes mal was anderes am port hängt, habe ich mir
aber bisher keine gedanken drüber gemacht !!

Also nochmals besten Dank !!!
Erstelle mir aus dem ganzen Basiswissen über uc - programmierung grad
ne "Formelsammlung", welche dn Einstig erleichtern soll, werde sie
natürlich veröffentlichen, wenns fertig ist !!

Bis dann

von Bri (Gast)


Lesenswert?

Ist das wirklich notwendig? Hier steht doch alles:

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial

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.