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.
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 ??
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)); |
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.
Das ist auch richtig so. Die kleinste Einheit in C ist ein Byte. Alle Manipulationen arbeiten immer mindestens auf einem Byte.
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.
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
> 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)
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...
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.
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!
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.
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.
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!
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
sty, muss jetzt kurz trollen: oder du verwendest micropascal und schreibst den einzeiler: bit:=portD.2; :)
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.
Schon klar, nur eben das mikropascal auch als nicht-kommerzielle version mit lediglich einer 4K beschränkung zu haben ist.
wie wäre es mit bitfeld.bitA = !!(PIND & (1 << PIND2) in c99 dürfe auch das gehen: bitfeld.bitA = (_Bool)(PIND & (1 << PIND2)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.