Hallo liebes Forum, ich habe ein Problem für das ich eure Hilfe brauche. Auf einem ATMEGA16 möchte ich einen einzelnen Port (B) als Ein- UND Ausgang verwenden, sprich PIN0 ist Eingang und PIN1 ist Ausgang. Das geht auch relativ einfach mit dem Befehl "DDRB = 0bXXXXXX01". Das Problem ist nun, wie kann ich einen einzelnen Eingang ABFRAGEN? Kann man nur ein ganzes Byte abfragen ( [...] if(PORTB == 0b00000010){ ... } [...] ) oder ist auch ein einzelnes Bit möglich? Beim Googeln habe ich leider keine Lösung für dieses Problem gefunden. Vielen Dank schon mal für eure Hilfe! Berndy
Bernd Hauegg schrieb: > Das geht auch relativ einfach mit dem Befehl "DDRB = 0bXXXXXX01". > > Das Problem ist nun, wie kann ich einen einzelnen Eingang ABFRAGEN? > Kann man nur ein ganzes Byte abfragen ( [...] if(PORTB == 0b00000010){ > ... } [...] ) oder ist auch ein einzelnes Bit möglich? Zunächst mal willst du nicht den PORTB abfragen, sondern den PINB. PORTx die Ausgangsbits PINx die Eingangsbits und das andere, was dir noch fehlt, sind die Möglichkeiten die du hast, mittels Bitoperationen das gelesene Byte so zu manipulieren, dass dir am Ende nur dieses 1 Bit übrig bleibt, welches dich interessiert. D.h. du liest nach wie vor den kompletten PINB als 1 Byte ein. Aber danach bearbeitest du dieses Byte so, dass alle Bits, die dich NICHT interessieren, definitiv und ganz sicher auf 0 gesetzt werden. Dann bleibt nur dieses eine Bit übrig und der Wert des so manipulierten Bytes ist dann entweder 0 (dann ist auch das Bit 0) oder das Byte ist nicht 0 (dann ist dieses eine Bit auf 1) Bitmanipulation > "DDRB = 0bXXXXXX01". und mit genau denselben Methoden willst du auch das DDRB bearbeiten. Nicht indem du ihm als ganzes einen Wert zuweist, sondern indem du gezielt nur das eine Bit 0 auf 1 setzt. Denn mit einer einfachen Zuweisung veränderst du ALLE 8 Bit. Das kannst du nicht verhindern. Aber du kannst den momentanen Wert des Bytes in DDRB nehmen, dort gezielt mit einer Oder-Operation das 1 Bit zuätzlich setzen und dann das so manipulierte Byte wieder insd DDRB zurückschreiben. Der Effekt ist, dass bereits bestehende Bits in DDRB (die du so verschämt mit XXXXXX bezeichnet hast) garantiert nicht verändert werden. Und genau das willst du haben! Du möchtest dich davon befreien, dass du dir merken musst, wie die restlichen XXXXXX Bits gerade stehen, wenn du das Bit 0 auf 1 setzen willst. Denn solche Dinge sind ansonsten sehr fehleranfällig. Heute weißt du noch, dass du bei DDRB = 0b00000001; die höherwertigen Bits alle auf Eingang gestellt werden und das das auch gut so ist. Aber wenn deine Programme größer werden und du an einem Port 3 LED und 5 Taster hast, dann weißt du nicht mehr so schnell, welche DDR Bits jetzt 1 und welche 0 sein müssen. > Beim Googeln habe ich leider keine Lösung für dieses Problem gefunden. Fang mit dem >>>AVR-GCC-Tutorial<<< als deine erste Anlaufstelle an. Dort finden sich solche Dinge, die dir für den Anfang den Weg erleichtern.
1 | #include <avr/io.h> |
2 | |
3 | #define TASTER PB1
|
4 | #define LED PB0
|
5 | |
6 | int main() |
7 | {
|
8 | DDRB |= ( 1 << LED ); // den Pin mit der Led auf Ausgang |
9 | // setzen, indem im DDRB dafür ein 1 Bit
|
10 | // eingetragen wird
|
11 | |
12 | DDRB &= ~( 1 << TASTER ); // den Pin mit dem Taster auf Eingang setzen |
13 | // indem im DDRB dafür ein 0 Bit eingetragen wird
|
14 | |
15 | PORTB |= ( 1 << TASTER ); // den Pullupwiderstand einschalten, indem am PORTB |
16 | // das Bit für den Eingang auf 1 gesetzt wird.
|
17 | |
18 | while( 1 ) { |
19 | if( PINB & ( 1 << TASTER ) ) // ist das Bit an dem der Taster hängt |
20 | // auf 1?
|
21 | PORTB |= ( 1 << LED ); // Ja: Das Ausgangsbit an dem die LED hängt |
22 | // auf 1 setzen
|
23 | else
|
24 | PORTB &= ~( 1 << LED ); // Nein: Das Ausgangsbit an dem die LED |
25 | // hängt auf 0 setzen
|
26 | }
|
27 | }
|
Vorsicht! Beim Einlesen PINB verwenden! PORTB steuert nur die Ausgänge! Man kann PORTB zurücklesen, bekommt aber nur den Wert der aktuell eingestellten Ausgänge wieder! PINB hingegen liefert den Eingangswert. Einzelne Bits kann man nicht lesen, nur die ganzen 8 Bit des Ports B. Wenn Du einzelen Bits brauchst --> Bitmanipulation z.B. bei Dir:
1 | char Bit_Status |
2 | |
3 | int main(void) |
4 | {
|
5 | ....
|
6 | Bit_Status = ((PINB & (1<<PIN0)) != 0); //Bit_Status hält den Zustand Pin0 |
7 | ....
|
8 | }
|
Sepp schrieb: > Einzelne Bits kann man nicht lesen, nur die ganzen 8 Bit des Ports B. Man kann z.B. auf Assembler-Ebene zumindest mit den SKIP-Befehlen auch einzelne Bits abfragen, aber scheint hier wohl um C zu gehen. Der Compiler nutzt ggf. solche Befehle intern, aber auf C-Ebene schreibt man trotzdem immer den Zugriff auf das ganze Byte hin.
>Man kann z.B. auf Assembler-Ebene zumindest mit den SKIP-Befehlen auch >einzelne Bits abfragen, aber scheint hier wohl um C zu gehen. das ist schon richtig, aber wenn man eine Zuweisung zu einer Variablen machen will geht's nicht mehr. P.S.: .... if (PINB & (1<<PIN0)) { } .... wird der Compiler in EINEM Befehl (ala "Skip if bit 0 is set") abarbeiten! Auch wenn die Zeile nach mehr gerneriertem (Assembler-)Code aussieht.
Hallo, vielen Dank für eure tollen Antworten! Die Beitrage haben sich wunderbar ergänzt. Besonders gut — und wichtig — waren die theoretischen Grundlagen mit dem Artikel von Karl Heinz Buchegger. Die Abfrage selbst hat mit dem Code von Sepp (Gast) hervorragend funktioniert:
1 | char Bit_Status |
2 | int main(void) |
3 | {
|
4 | ....
|
5 | Bit_Status = ((PINB & (1<<PIN0)) != 0); //Bit_Status hält den Zustand Pin0 |
6 | ....
|
7 | }
|
Vielen Dank auch an Falk Brunner und Rolf Magnus für ihre Beiträge! Herzliche Grüße Bernd Hauegg
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.