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


von Stephan Maier (Gast)


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.

von Alex B. (Firma: Ucore Fotografie www.ucore.de) (alex22) Benutzerseite


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

von Johannes M. (johnny-m)


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
1
bitfield.bit = 1 && (PIND & (1 << PIND2));

von Stephan Maier (Gast)


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.

von Karl H. (kbuchegg)


Lesenswert?

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

von F. K. (freddy436)


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.

von Stephan Maier (Gast)


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

von Karl H. (kbuchegg)


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)

von Johannes M. (johnny-m)


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

von F. K. (freddy436)


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.

von Johannes M. (johnny-m)


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!

von F. K. (freddy436)


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.

von Johannes M. (johnny-m)


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.

von Stephan Maier (Gast)


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!

von Peter D. (peda)


Lesenswert?

Man kann die Portpins sehr einfach als Bits definieren und verwenden:
1
#include <io.h>
2
3
struct bits {
4
  uint8_t b0:1;
5
  uint8_t b1:1;
6
  uint8_t b2:1;
7
  uint8_t b3:1;
8
  uint8_t b4:1;
9
  uint8_t b5:1;
10
  uint8_t b6:1;
11
  uint8_t b7:1;
12
} __attribute__((__packed__));
13
14
#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)
15
16
17
#define KEY0            SBIT( PINB, 0 )
18
#define KEY0_PULLUP     SBIT( PORTB, 0 )
19
20
#define LED0            SBIT( PORTB, 1 )
21
#define LED0_DDR        SBIT( DDRB, 1 )
22
23
24
int main( void )
25
{
26
27
  LED0_DDR = 1;         // output
28
  KEY0_PULLUP = 1;      // pull up on
29
30
  for(;;){
31
32
    if( KEY0 == 0 )     // if key pressed (low)
33
      LED0 = 0;         // LED on (low)
34
    else
35
      LED0 = 1;         // LED off (high)
36
  }
37
}



Peter

von mik (Gast)


Lesenswert?

sty, muss jetzt kurz trollen:

oder du verwendest micropascal und schreibst den einzeiler:

bit:=portD.2;

:)

von Johannes M. (johnny-m)


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.

von mik (Gast)


Lesenswert?

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

von Gerard Choinka (Gast)


Lesenswert?

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

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

von Johannes M. (johnny-m)


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.

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.