PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Wertezuweisungen an BIT



Antropath
16.01.2010, 16:06
Hallo!

Ich versuche mich gerade etwas in die Programmierung von AVRs reinzulesen. Wie man den Zusammenhängen entnehmen kann versuche ich das in C, da ich mit dieser Programmiersprache schon etwas Erfahrung habe.


Für den Anfang habe ich mich zum Erlernen der Basics auf diese HP beschränkt:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial

Ich merke aber schon, dass es bei mir hauptsächlich an den Hardware-Kenntnissen scheitert und in Folge dessen, ist mir vollkommen schleierhaft weshalb man einem Pin in einem Port folgendermaßen einen Wert zuordnet:

x |= (1 << Bitnummer); // Hiermit wird ein Bit in x gesetzt
x &= ~(1 << Bitnummer); // Hiermit wird ein Bit in x geloescht

// -------------------


#include <avr/io.h>
...
#define MEINBIT 2
...
PORTA |= (1 << MEINBIT); /* setzt Bit 2 an PortA auf 1 */
PORTA &= ~(1 << MEINBIT); /* loescht Bit 2 an PortA */

Für Hilfe
Wäre ich Dankbar
PS:Bit-Operatoren kenne ich eigentlich, aber wie sie hier verwendet werden versteh ich nicht.

oberallgeier
16.01.2010, 16:25
Hallo Antropath,

hmmm - Du bist einfach nicht über den Link zur Bitmanipulation in Deinem Tutorial gestolpert:

http://www.mikrocontroller.net/articles/Bitmanipulation

Dort sollte alles viel besser erklärt sein, als ich es könnte. Ich hoffe, dass Du es damit dann verstehst.

Ach so - ja: ein Port hat acht Pinns. Das gilt theoretisch, praktisch sind nicht bei allen Controllern immer alle Portpins verfügbar. Diese Portpins sind duchnummeriert, wie es die Informatiker machen, also von ein 0 bis 7. Daher kann man "en bloc" - also alle Pinns auf einmal so definieren:


// Pins/Ports als Ein- (0) oder Ausgänge (1) konfigurieren, Pull Ups (1) aktivieren
// A = Ausgang, E = Eingang ohne , EU = Eingang MIT PullUp
DDRB = 0b10011111; // siehe aktuell oben oder Fortschritt/R2D2
PORTB = 0b01100000; // und Port/Pull Ups (1) aktivieren

Damit werden die Portpins PORTB0 bis PORTB7 definiert und das zugehörige Datenrichtungsbit DDRB an der gewünschte Stelle gesetzt. Deine Codeschnippsel betreffen die Manipulation EINZELNER Bits. Die ist auch möglich - und manchmal auch zwingend erforderlich.

Übrigens kannst Du mit dieser Bitmanipulation nicht nur einzelne Portpins "bearbeiten". Die Zuweisung eines 1-Byte-Wertes ist damit auch möglich. Das ist aber (glaube ich) auch im Tutorial erklärt.

radbruch
16.01.2010, 16:36
Hallo


Dort sollte alles viel besser erklärt sein, als ich es könnte.Dem kann ich zustimmen, ich hatte es hier (im Folgenden) auch mal versucht zu erklären:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=295539#295539

Gruß

mic

oberallgeier
16.01.2010, 16:53
Dort sollte alles viel besser erklärt sein, als ich es könnte.Dem kann ich zustimmen ...Na ich hoffe, dass Du damit jetzt nicht feststellst, dass meine Erklärungen so be...scheiden sind *ggg*.

Antropath
16.01.2010, 17:14
Hallo!

Euere Antoworten haben mir geholfen, das Grundprinzip hab ich verstanden.
@oberallgeier: nein, deine war schon auch hilfreich.^^

Eine kurze Zwischenfrage:
reg_32 |= (1 << MEINBIT15); /* FEHLER: Setzt die Bits 31 - 15, da
((int)1 << 15) == 0xFFFF8000 */
Was bedeuter dieses 0xFFFF8000 denn genau? wäre es das F wie im HEX-DEZ-System, so wäre die Zahl doch riesig.
Aber eben so macht man dass ja nicht.
Achja...falls das nicht klar war. Im obigen Beispiel wollte man das 15.Bit setzen, obwohl reg_32 eine 32-Bit-weite Variable ist.

Was ich versehe ist, dass das bei der Verschiebung den Rahmen eines normalen int sprengt. Aber wieso werden dann genau die Bit 31-15 gesetzt?

MfG Antro

radbruch
16.01.2010, 17:37
@oberallgeier :

Dem kann ich zustimmen......ich kann es selbst nicht besser erklären. Das war schon abgesendet bevor du dein Edit/Erklärungsversuch abgesetzt hattest ;)

Die Bitmaske 0xFFFF8000 entspricht 0B11111111111111111000000000000000 (17 mal 1 und 15 mal 0)

Warum ((int)1 << 15) aber 0xFFFF8000 ergeben soll, ist mir so aus dem Stand etwas unklar. Ich hätte erwartet, dass die fehlenden Bits 16-31 mit 0 aufgefüllt werden.

Vielleicht wurde MEINBIT15 als 16bit Variable deklariert und dies als 16bitigen Grenzwert für ((int)1 << 15) angesehen? Das würde die Verwirrung erklären.

Gruß

mic

sternst
16.01.2010, 18:16
Warum ((int)1 << 15) aber 0xFFFF8000 ergeben soll, ist mir so aus dem Stand etwas unklar. Ich hätte erwartet, dass die fehlenden Bits 16-31 mit 0 aufgefüllt werden.Weil die 1 ein signed int ist. Das <<15 schiebt das gesetzte Bit ins Vorzeichen und somit ergibt sich als Ergebnis -32768. Das auf 32 Bit erweitert ergibt das Bitmuster 0xFFFF8000 (die FFFF sind das Resultat der Sign-Extension).

Einfache Abhilfe:
"(1U<<15)", "(1UL<<15)" oder ein Typcast für die 1.

radbruch
16.01.2010, 18:29
Weil die 1 ein signed int ist. Das <<15 schiebt das gesetzte Bit ins VorzeichenKrass. Danke für die Info. Dann würde wohl ein ((unsigned int)1 << 15) auch funktionieren?

Aber warum ist das dann ein Fehler? Hier gibt es kein Typcast.
reg_32 |= (1 << MEINBIT15); /* FEHLER: Setzt die Bits 31 - 15, da ((int)1 << 15) == 0xFFFF8000 */

Für was steht dabei MEINBIT15? Da fehlt jetzt eindeutig der Kontext ;)

sternst
16.01.2010, 18:38
Dann würde wohl ein ((unsigned int)1 << 15) auch funktionieren?Ja.

Antropath
16.01.2010, 23:13
Hallo!

Vielen Dank.
Wenn man sich das ganze einmal genau durchdenkt, so ist zumindest die Frage mit den Fs eigentlich schon beantwortet. Jede Stelle im HEX-DEZ System ersetzt ja 4 stellen im binären System. D.h. F(16) äquivalent 1111(2).

Gruß
Antro