Pages: [1]   Go Down
Author Topic: booleans in byte speichern  (Read 289 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
God Member
*****
Karma: 2
Posts: 533
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,

ich würde gerne mehrere Boolean-Variablen (?) in einem Byte speichern.

Code:
boolean t1_st;
boolean t2_st;
boolean t3_st;
boolean t4_st;
boolean t5_st;
boolean fz_st;

byte t_st = (t1_st << 0 | t2_st << 1 | t3_st << 2 | t4_st << 3 | t5_st << 4 | fz_st << 5);

In den einzelnen "Booleans" speichere ich Tastzustände.

Wenn nun Taster 2, 5 und fz gedrückt sind, soll byte t_st so lauten:

Code:
t_st == B00110010

Momentan scheint dies jedoch noch nicht zu funktionieren, weil sich der jeweilige buttonstate nicht selbständig in t_st schreibt und ich nicht weiss, wie ich dies bewerkstelligen könnte. Auszug (für eine Taste):

Code:
void t_de_st()
{
  t1_old_st = t1_st;  // 3. "neuen Status" speichern

  t1_Bouncer.update ( );  // 1. Entprellten Zustand "erfragen"

  t1_st = t1_Bouncer.read();  // 2. Tastenstatus aktualisieren

  if (t1_st != t1_old_st)                               
  {                         
    if (t1_st)                                       
    {
      Serial.println("\t\t\t\t\t\tTaste 1 wurde gedrueckt");
      t_hold_time = millis();
    }
    else if (!t1_st)
    {
      Serial.println("\t\t\t\t\t\tTaste 1 wurde losgelassen");
      t_hold_st--;
    }
  }
}

Gruß Chris
« Last Edit: November 21, 2013, 10:50:20 am by Chris72622 » Logged


Offline Offline
Faraday Member
**
Karma: 79
Posts: 2733
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Funktioniert bei mir in Visual C++

Code:
bool t1_st = true;
bool t2_st = true;
bool t3_st = false;
bool t4_st = false;
bool t5_st = true;
bool fz_st = false;

unsigned char t_st = (t1_st << 0 | t2_st << 1 | t3_st << 2 | t4_st << 3 | t5_st << 4 | fz_st << 5);

cout << bitset<8>(t_st) << endl;

Ausgabe: 00010011

Ist wie gesagt C++/.NET und läuft so nicht auf dem Arduino, aber ich habe nur die Datentypen und die Ausgabe angepasst.


Was auch geht ist das:
Code:
struct bitfield
{
unsigned char t1_st : 1;
unsigned char t2_st : 1;
unsigned char t3_st : 1;
unsigned char t4_st : 1;
unsigned char t5_st : 1;
unsigned char fz_st : 1;
};

union memory
{
unsigned char asByte;
struct bitfield asBits;
};

memory bits;
bits.asByte = 0;
bits.asBits.t1_st = true;
bits.asBits.t3_st = true;

Ausgabe: 000000101

Die Union hat den Vorteil, dass wenn man auf das Bitfeld zugreift sich automatisch die Variable "asByte" ändern. Also ist eine extra Zuweisung nicht mehr nötig
« Last Edit: November 21, 2013, 03:01:11 pm by Serenifly » Logged

Offline Offline
God Member
*****
Karma: 2
Posts: 533
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Fehler (vermutlich) gefunden:

Die Zeile..

Code:
t_st = (t1_st << 0 | t2_st << 1 | t3_st << 2 | t4_st << 3 | t5_st << 4 | fz_st << 5);

..muss ja nach jeder Tastenabfrage erneut erfolgen. Dies hatte ich vergessen. Ich hatte nur einmalig..

Code:
byte t_st = (t1_st << 0 | t2_st << 1 | t3_st << 2 | t4_st << 3 | t5_st << 4 | fz_st << 5);

..angegeben.

Dass ich zu wenig Code gepostet hatte, damit jmd. dies hätte erkennen können, ist mir im nachhinein klar.  smiley-zipper

Gruß Chris
Logged


Offline Offline
Faraday Member
**
Karma: 79
Posts: 2733
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ja. Du musst das immer updaten.

Daher der Vorschlag mit der Union, dann ist das nicht nötig. Bei Unions belegen alle Variablen den gleichen Speicherplatz. Ändert man eine, dann ändern sich automatisch die anderen. Und mit dem Bitfeld kann man einzelne Bits in beliebigen Datentypen speichern.

Siehe hier:
http://www.c-howto.de/tutorial-strukturierte-datentypen-bitfelder.html
http://www.c-howto.de/tutorial-strukturierte-datentypen-vereinigung-union.html
Logged

Offline Offline
God Member
*****
Karma: 2
Posts: 533
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich habe mal versucht, das von Dir Gepostete "arduinogerecht" aufzubereiten, aber es compiliert noch nicht.

Warum hast Du mit unsigned char gearbeitet?

Gruß Chris

Code:
struct bitfield{
unsigned char t1_st :
  1;
unsigned char t2_st :
  1;
unsigned char t3_st :
  1;
unsigned char t4_st :
  1;
unsigned char t5_st :
  1;
unsigned char fz_st :
  1;
};

void setup()
{
}

void loop()
{
}

union memory
{
  unsigned char asByte;
  struct bitfield asBits;
};

memory bits;
bits.asByte = 0;
bits.asBits.t1_st = 1;
bits.asBits.t3_st = 1;
Logged


Offline Offline
Faraday Member
**
Karma: 79
Posts: 2733
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Weil ich das in .NET getestet habe und es da keinen Datentyp "byte" gibt smiley Byte = unsigned char. Kannst du auch auf byte ändern.

Das mit dem :1 gehört eigentlich in die gleiche Zeile. Das heißt, dass diese Variable ein Bit belegt. Macht aber funktional keinen Unterschied.

Das Problem hier ist, dass die Zuweisungen auf die Union Variablen in eine Methode müssen. Das geht irgendwie nicht global .NET meckert da auch, aber mit einem anderen Fehler. Genauso wie du nicht das global machen kannst:
Code:
int i;
i = 2;
Sowas geht immer nur einer Zeile als Initialisierung. Aber nicht als Zuweisung.

Wenn du "memory bits;" global machst kannst du dir "bits.asByte = 0;" auch sparen, da dann die Default-Initalisierung auf 0 greift. Die Zuweisungen auf die Bitfelder kommen dann sowieso irgendwo in loop.


Die Verwirrung da ist auch wieder bei copy/paste entstanden. Aus irgendeinem Grund habe ich das struct und die union innerhalb von main() deklariert. Das geht natürlich, aber eigentlich gehört es global. Dann waren die Zuweisungen auch in main() und ich habe einfach den Code kopiert, ohne den Methoden Rumpf. Dann hat es so ausgesehen als ob alles global sein sollte smiley-sad
« Last Edit: November 21, 2013, 02:44:46 pm by Serenifly » Logged

Offline Offline
God Member
*****
Karma: 2
Posts: 533
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Du würdest mir einen riesen Gefallen machen, wenn Du mir den Code, so wie Du ihn letztendlich für richtig hälst einfach noch einmal hochladen würdest. Ich bin Anfänger, nehme den Code mit Hilfe des Internets seit einer halben Stunde Stück für Stück auseinader und bleibe dabei leicht hängen.  smiley-slim

Wär echt super.

Dank Dir.

Gruß Chris
Logged


Offline Offline
Faraday Member
**
Karma: 79
Posts: 2733
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Einfach die Zuweisungen in loop packen, bzw. in irgendeine andere Methode:

Code:
struct bitfield
{
   byte t1_st :  1;
   byte t2_st :  1;
   byte t3_st :  1;
   byte t4_st :  1;
   byte t5_st :  1;
   byte fz_st :  1;
};

union memory
{
  byte asByte;
  struct bitfield asBits;
};

memory bits;

void setup()
{
}

void loop()
{
   bits.asBits.t1_st = 1;
   bits.asBits.t3_st = 1;

   Serial.println(bits.asByte, BIN);
}

Das ist auch nur Test Code mit dem Teil in loop(). Du fragst ja da dann irgendwo deine Taster aber und setzt die Variablen.
Logged

Offline Offline
God Member
*****
Karma: 2
Posts: 533
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Dank Dir!

Ich wurstel dann mal weiter durch.   smiley-cool

Gruß Chris
Logged


Offline Offline
God Member
*****
Karma: 2
Posts: 533
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich bekomme es (zunächst mal ohne Bitfeld) nicht hin.   smiley-sad

Nachdem alle Taster abgefragt wurden habe ich momentan diese Zeile stehen:

Code:
t_st = (t1_st << 0 | t2_st << 1 | t3_st << 2 | t4_st << 3 | t5_st << 4 | fz_st << 5);

Offensichtlich kommt da aber nur Müll dabei heraus.

Wie könnte ich denn noch die einzelnen Tastzustände in mein Byte bekommen, ohne dabei die zwei letzten Bits des Bytes zu verändern?

Gruß Chris
Logged


Offline Offline
Faraday Member
**
Karma: 79
Posts: 2733
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

http://arduino.cc/en/Reference/BitWrite

Nicht getestet:
Code:
byte writeByte(byte b1, byte b2, byte b3, byte b4, byte b5, byte b6)
{
      byte b = 0;
      bitWrite(b, 0, b1);
      bitWrite(b, 1, b2);
      bitWrite(b, 2, b3);
      bitWrite(b, 3, b4);
      bitWrite(b, 4, b5);
      bitWrite(b, 5, b6);
      return b;
}

void loop()
{
      byte t_st = writeByte(t1_st, t2_st, t3_st, t4_st, t5_st, fz_st);
}

Quote
ohne dabei die zwei letzten Bits des Bytes zu verändern?
So wie es auch bei dir steht, schreibt er immer ein komplett neues Byte.

Wenn du das auf ein bestehendes Byte anwenden willst, kann man vorher das machen:
Code:
t_st &= 0xC0;
t_st |= (t1_st << 0 | t2_st << 1 | t3_st << 2 | t4_st << 3 | t5_st << 4 | fz_st << 5);
Damit wird erst mal alles bis auf die obersten zwei Bits gelöscht. Den Rest kann man dann neu setzen

Bei dem Code oben kann man das so machen:
Code:
byte writeByte(byte data, byte b1, byte b2, byte b3, byte b4, byte b5, byte b6)
{
      byte b = data & 0xC0;
      ...
}
Also noch das Byte übergeben und die neue Version zurückgeben. Könnte man auch mit einem Pointer machen.

« Last Edit: November 24, 2013, 08:54:49 pm by Serenifly » Logged

Offline Offline
God Member
*****
Karma: 2
Posts: 533
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
struct bitfield
{
   byte t1_st :  1;
   byte t2_st :  1;
   byte t3_st :  1;
   byte t4_st :  1;
   byte t5_st :  1;
   byte fz_st :  1;
};

union memory
{
  byte asByte;
  struct bitfield asBits;
};

memory bits;

void setup()
{
}

void loop()
{
   bits.asBits.t1_st = 1;
   bits.asBits.t3_st = 1;

   Serial.println(bits.asByte, BIN);
}

Ich habe mir jetzt diesen Code von Dir bestimmt mind. 20 Mal angeschaut, verstehe aber bis auf die Erstellung des Bitfeldes nichts.

Insbesondere die Zeilen in der es um die Erstellung einer Union geht und diese hier..

Code:
memory bits;
Code:
bits.asBits.t1_st = 1;

..verstehe ich leider gar nicht. Den Seiten, auf denen erklärt wird was eine Union ist, kann ich lediglich entnehmen, dass sich bei einer Union mehrere Variablen einen Speicherplatz teilen. Leider aber kann ich das noch immer nicht in Verbindung mit dem oben bereits von Dir geposteten Code bringen.

Vielleicht möchtest Du Dich ja nochmal erbarmen, mich mit ein paar Kommentaren (oder Links) zu erleuchten..?

Gruß Chris
Logged


Offline Offline
Faraday Member
**
Karma: 79
Posts: 2733
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ein struct ist nichts anderes als eine Sammlung von einer Variablen, die man unter einem Namen ansprechen kann. Das ganze ähnelt einem Objekt (und in C++ können structs auch Funktionen und Konstruktoren enthalten). Ein Bitfeld ist eine besondere Variante davon bei der man mit ": x" angibt wie viele Bits eine Variable belegen soll.

Code:
memory bits;
Die Union heißt "memory" und wir legen einen Variable davon an die "bits" heißt. Das ist genauso wie wenn man in einer OOP Sprache ein Objekt einer Klasse instantiiert - z.B. das: LiquidCrystal lcd(...)
Statt "bits" kannst du auch einen anderen Namen wählen. Das ist nur ein Variablenname

Code:
bits.asBits.t1_st = 1;
Die Union enthält die zwei Elemente "asBits" (das Bitfeld) und "asByte" (das Byte/unsigned char). Genauso wie man bei Objekten auf die internen Methoden und Variablen zugreift, muss man hier auch auf die entsprechenden Elemente zugreifen.

Mit "bits.asBits" hat man dann das Bitfeld struct. Das enthält wiederum Elemente auf die man zugreifen kann/muss. Daher
"bits.asBits.t1_st" -> union.struct.bit


Sowas kann man sehr schön in einer IDE mit Autovervollständigung ausprobieren. Da tippt man dann den Punkt an und sieht sofort welche Elemente man danach auswählen kann. Für den Arduino gibt es da Atmel Studio. Oder eine Vollversion von Visual Studio mit dem Visual Micro Plugin (mit Visual C++ Express geht es aber nicht).
Logged

Pages: [1]   Go Up
Jump to: