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
Siehe Bitmanipulation
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 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
Gast
#2955822
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 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
Gast
#2955855
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.
Gast
#2956142
>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 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
Vielen Dank auch an Falk Brunner und Rolf Magnus für ihre Beiträge! Herzliche Grüße Bernd Hauegg
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.