Atmega8/1 PortPin als Bit speichern

Gast #654185
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.
#654205
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));
Gast #654207
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.
#654213
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.
Gast #654244
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
#654249
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)
#654251
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...
#654262
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!
#654264
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.
#654267
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.
#654276
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
#654567
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren