mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Atmega8/1 PortPin als Bit speichern


Autor: Stephan Maier (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo erstmal!
Ich quäle mich jetzt schon einige Zeit mit dem Problem, dass ich den 
Zustand von PIND2 als Bit in eine Variable speichern möchte.

Die einzige Lösung, die ich gefunden habe, womit ich wirklich den 
Zustand des  Bits PIND2 abfragen kann ist: "if(PIND&(1<<PIND2))"

Ich habe ein Bitfeld angelegt und wollte nur den Zustand von PIND2 
abspeichern und dann mittels dieser Variable einen Ausgangspin setzen. 
Leider funktioniert das nicht. Ich kann nur den ganzen Port D einlesen 
und dann entsprechend der Wertigkeit des PIND2 den Zustand abfragen.
In der Beschreibung steht aber, dass eben "PINx.n" dazu verwendet werden 
kann, den Zustand eines Eingangpins abzufragen.

Vielleicht habe ich ja nur ein Verständnisproblem - jedenfalls wäre es 
nett, wenn mir jemand das erklären könnte.

Autor: Alex Bürgel (Firma: Ucore Fotografie www.ucore.de) (alex22) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich kenne mich leider nur mit PIC's aus. Beim CC5X Compiler geht es 
wirklich mit z.B. PORTA.2 (3. Pin von Port A).
Geht das bei Atmels nicht mit z.B. PA2 ??

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex Bürgel wrote:
> Ich kenne mich leider nur mit PIC's aus. Beim CC5X Compiler geht es
> wirklich mit z.B. PORTA.2 (3. Pin von Port A).
> Geht das bei Atmels nicht mit z.B. PA2 ??
Nein, das geht beim WINAVR-Compiler nicht (und ist auch nicht ANSI-C). 
Was aber gehen könnte, ist
bitfield.bit = 1 && (PIND & (1 << PIND2));

Autor: Stephan Maier (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich beziehe mich mit meiner Frage auf das AVR-GCC Tutorial von dieser 
Homepage. Bei der Beschreibung über die Ports wird ja erklärt, dass man 
zuerst mal die Datenrichtung festlegt usw.
Außerdem lässt sich ja eine Abfrage mit dem Eintrag "PIND2" (für meinen 
Versuch) durchführen - eben nur in dieser Weise: "if(PIND&(1<<PIND2))"
Möchte ich jedoch den Zustand von "PIND2" in eine Variable speichern 
(z.B.: x.pin = PIND2), welche ich auch noch als Bitvariable definiert 
habe, und danach "x.pin" in Verzweigungen abfrage, geht das nicht.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist auch richtig so.
Die kleinste Einheit in C ist ein Byte. Alle Manipulationen
arbeiten immer mindestens auf einem Byte.

Autor: F. Kriewitz (freddy436)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich vermute das du sowas vorhast:
Bits.Bit0 = PIND&(1<<PD2);
Das funktioniert nicht weil die Bit Variable nur auf das 2^0 Bit 
reagiert, du musst also das Bit nach rechts shiften.

das sollte funktionieren:
Bits.Bit0 = (PIND&(1<<PD2))>>PD2;

EDIT:
Wenn ich mich recht erinnere ist ein if(PIND&(1<<PD2))/else einen Tick 
schneller/kleiner als die shifterei.

Autor: Stephan Maier (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also danke erstmal für die schnellen Antworten - deshalb finde ich 
dieses Forum/diese Homepage auch so gut (Lob muß auch mal sein).

Prinzipiell kann ich ja den Zustand abfragen - ich wollte / möchte 
eigentlich nur wissen, warum ich den Zustand des Bit "PIND2" im Register 
"PIND" nicht direkt in eine Bitvariable abspeichern und dann wie folgt 
verarbeiten kann:

"struct{
   x.pin:1;
}x;

....
....

x.pin = PIND2;
if(x.pin==0)
   tu dies;
if(x.pin ==1)
   tu das

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> warum ich den Zustand des Bit "PIND2" im Register
> "PIND"

Sagte ich doch schon. Die kleinste Einheit ist nun
mal ein Byte. Das Register PIND kann nur als ein
komplettes Byte ausgelesen werden.

Natürlich steht es einem frei, mittels UND und ODER
Operationen irgendwelche Maskieroperationen anzubringen,
aber tief im innersten arbeitet ein µC (zumindest ein
AVR) immer mit ganzen Bytes (abgesehen von ein paar
Spezialbefehlen die tatsächlich auf nur 1 Bit in einem
Byte operieren, wie zb sei)

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
F. Kriewitz wrote:
> EDIT:
> Wenn ich mich recht erinnere ist ein if(PIND&(1<<PD2))/else einen Tick
> schneller/kleiner als die shifterei.
Wenn der Compiler schlau ist, dann macht er aus dem if(PIND & (1 << 
PIND2)) eine sbis-Intruktion. Schneller und kürzer geht es vermutlich 
gar nicht. Es sieht nur u.U. im C-Code ein bisschen sperrig aus. 
Allerdings habe ich Zweifel, dass der Compiler das tatsächlich macht...

Autor: F. Kriewitz (freddy436)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich versuchs nochmal:

PIND&(1<<PD2)
ergibt z.B.:
0b00000100
Für if ist das true (da != 0)

Bitvariable interessieren sich aber nur für das ersten (2^0, etc.) 
Bit(s).
0bXXXXXXX1
Die anderen Bits werden praktisch ignoriert.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
F. Kriewitz wrote:
> Ich versuchs nochmal:
>
> PIND&(1<<PD2)
> ergibt z.B.:
> 0b00000100
> Für if ist das true (da != 0)
>
> Bitvariable interessieren sich aber nur für das erste (2^0) Bit.
> 0bXXXXXXX1
> Die anderen Bits werden praktisch ignoriert.
Hast Du das gesehen, was ich oben geschrieben habe? Wenn man den 
Compiler zwingt, das "PIND & (1 << PIND2)" als Wahrheitswert zu nehmen, 
ist sämtliche Schieberei überflüssig!

Autor: F. Kriewitz (freddy436)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johannes M. wrote:
> Hast Du das gesehen, was ich oben geschrieben habe? Wenn man den
> Compiler zwingt, das "PIND & (1 << PIND2)" als Wahrheitswert zu nehmen,
> ist sämtliche Schieberei überflüssig!
Klar, habe ich ja oben auch schon geschrieben das ein if die bessere 
Lösung ist.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
F. Kriewitz wrote:
> Johannes M. wrote:
>> Hast Du das gesehen, was ich oben geschrieben habe? Wenn man den
>> Compiler zwingt, das "PIND & (1 << PIND2)" als Wahrheitswert zu nehmen,
>> ist sämtliche Schieberei überflüssig!
> Klar, habe ich ja oben auch schon geschrieben das ein if die bessere
> Lösung ist.
Ich rede nicht von dem if sondern von meinem Posting um 10:00 Uhr! Das 
mit dem if geht wie gesagt nur theoretisch. Der Compiler ist leider 
nicht schlau genug, da ein sbis draus zu machen.

Autor: Stephan Maier (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, alles klar!
Da hatte ich einfach einen Denkfehler.

Danke nochmals für die vielen und schnellen Antworten! Wünsche 
allerseits ein schönes Wochenende!

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man kann die Portpins sehr einfach als Bits definieren und verwenden:
#include <io.h>

struct bits {
  uint8_t b0:1;
  uint8_t b1:1;
  uint8_t b2:1;
  uint8_t b3:1;
  uint8_t b4:1;
  uint8_t b5:1;
  uint8_t b6:1;
  uint8_t b7:1;
} __attribute__((__packed__));

#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)


#define KEY0            SBIT( PINB, 0 )
#define KEY0_PULLUP     SBIT( PORTB, 0 )

#define LED0            SBIT( PORTB, 1 )
#define LED0_DDR        SBIT( DDRB, 1 )


int main( void )
{

  LED0_DDR = 1;         // output
  KEY0_PULLUP = 1;      // pull up on

  for(;;){

    if( KEY0 == 0 )     // if key pressed (low)
      LED0 = 0;         // LED on (low)
    else
      LED0 = 1;         // LED off (high)
  }
}



Peter

Autor: mik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sty, muss jetzt kurz trollen:

oder du verwendest micropascal und schreibst den einzeiler:

bit:=portD.2;

:)

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mik wrote:
> oder du verwendest micropascal und schreibst den einzeiler:
>
> bit:=portD.2;
In kommerziellen Embedded-C-Compilern mit entsprechenden 
nicht-ANSI-Erweiterungen geht das auch, da brauchts kein Pascal für. 
Aber es geht eben nicht in WINAVR-C.

Autor: mik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schon klar, nur eben das mikropascal auch als nicht-kommerzielle version 
mit lediglich einer 4K beschränkung zu haben ist.

Autor: Gerard Choinka (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wie wäre es mit
bitfeld.bitA = !!(PIND & (1 << PIND2)

in c99 dürfe auch das gehen:
bitfeld.bitA = (_Bool)(PIND & (1 << PIND2)

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
An die doppelte logische Negation hatte ich auch schon gedacht. Auf 
welche Weise man es macht, ist aber relativ egal. Der Trick ist nur, 
dass man aus dem ursprünglichen Wert einen Wahrheitswert macht, der 
entweder 0 oder 1 sein kann. Und den kann man ohne Informationsverlust 
einem einzelnen Bit zuweisen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.