Forum: Mikrocontroller und Digitale Elektronik Bits aus Variable lesen


von F. H. (avrfreak)


Lesenswert?

Hi,

Ich weis nicht ich finde einfach keine Lösung um aus einer Variable die 
Bits auszulesen. Vlt stelle i mich auch einfach dumm an.

Hier mal ein Beispiel:


int main(void){

    int array[3] = {0x07, 0xEF, 0xA3}

    //jetzt möchte ich Beispielsweise aus array[2] die Bits auslesen
}


Wie funktioniert das? Muss i irgend etwas anders machen?

Vielen Dank schon mal im Vorraus.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Was heißt für Dich "die Bits auslesen"?

von F. H. (avrfreak)


Lesenswert?

also bei array[2] is das ja 0xEF
also binär 0b1110 1111
und so möchte ich eben mit den einzelnen bits arbeiten

also ich möchte prinzipiel nur den binären wert der Variable auslesen

: Bearbeitet durch User
von Lutz H. (luhe)


Lesenswert?

Bitte klären: wieviele Bits hat das int?
Dann durch bitweisen Test (Vergleichsoperationen die einzelnen Bits 
bestimmen), möglicherweise bringt auch printf etwas.

von Mark B. (markbrandis)


Lesenswert?

F. H. schrieb:
> also binär 0b1110 1111

Das ist keine Standard-Notation in C, deshalb lieber mit Vorsicht 
genießen.

von Karl H. (kbuchegg)


Lesenswert?

F. H. schrieb:

> also ich möchte prinzipiel nur den binären wert der Variable auslesen

auslesen ist schlecht ausgedrückt.

Aber was du tun kannst:
Du kannst natürlich feststellen, ob ein Bit auf 1 oder auf 0 ist. Und je 
nachdem machst du dann etwas anderes. Das funktioniert genau gleich, wie 
wenn man von einem Portpin feststellt ob er auf 1 oder auf 0 ist.
Sozusagen ein universeller Mechanismus.

Also. Nicht 'auslesen'.
Sondern: feststellen ob 1 oder 0 und dann darauf reagieren.

von Stefan R. (srand)


Lesenswert?

F. H. schrieb:
> also ich möchte prinzipiel nur den binären wert der Variable auslesen

Es gibt keinen "binären" oder "hexadezimalen" Wert. Es gibt nur einen 
Wert.

Was willst du wirklich? Die Binärdarstellung als String, also als 
Zeichenkette? Ein einzelnes Bit extrahieren? Etwas anderes?

von F. H. (avrfreak)


Lesenswert?

Okay Vielen Dank

also sollte das theoretisch so funktionieren...oder?

int main(void){

    int array[3] = {0x07, 0xEF, 0xA3}

    int iPIN1 = array[2] & (1<<0) //müsste ja dann eine 1 sein
    int iPIN5 = array[2] & (1<<4) //müsste ja dann eine 0 sein
}

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

F. H. schrieb:

>     int iPIN1 = array[2] & (1<<0) //müsste ja dann eine 1 sein

Ja, aber nur zufällig.

>     int iPIN5 = array[2] & (1<<4) //müsste ja dann eine 0 sein

Ja. aber auch nur zufällig.

Wenn im Ausgangswert ein 1 Bit gewesen wäre, dann wäre iPIN5 hier nicht 
1, sondern 32 (nämlich 1<<4)

Für iPIN1 stimmt das ganze zwar. Aber auch nur deswegen, weil es sich 
hier um das Bit 0 handelt, und die Wertigkeit dieses Bits ja nachdem 0 
oder 1 ist. Für die restlichen 7 Bits ist das zu kurz gedacht.

Die Grundidee ist allerdings korrekt. Wenn auch, je nachdem wie es dann 
weiter geht, unter Umständen nur die halbe Miete.

: Bearbeitet durch User
von F. H. (avrfreak)


Lesenswert?

okay und wie mach i das dann am besten?

von Stefan E. (sternst)


Lesenswert?

F. H. schrieb:
> okay und wie mach i das dann am besten?

Such dir eine Variante aus:
1
int iPIN5 = (_Bool)(array[2] & (1<<4));
2
int iPIN5 = (array[2] & (1<<4)) ? 1 : 0;
3
int iPIN5 = ((array[2] & (1<<4)) != 0);
4
int iPIN5 = !!(array[2] & (1<<4));

von F. H. (avrfreak)


Lesenswert?

ahja klar bin ich blöd

vielen dank für eure hilfe

von Karl H. (kbuchegg)


Lesenswert?

F. H. schrieb:
> okay und wie mach i das dann am besten?

Neben dem, was Stefan angeführt hat:

Am besten - gar nicht.

Wozu auch?
Wozu benötigst du die einzelnen Bits?
Das stellt man zuerst fest und danach entscheidet man, wie man dann an 
der verwendenden Stelle auf die Einzelbits zugreift. Je nachdem greift 
man nämlich nicht mehr so auf die einzelnen Bits jeder Stelle zu, 
sondern benutzt eine etwas andere, abgewandelte Technik. Im Grunde ist 
das zwar immer noch ein Maskieren und Verunden, aber man kann da einiges 
einsparen, wenn einen nicht interessiert ob da jetzt 0 oder 1 rauskommt, 
sondern 0 oder n auch schon reicht.

: Bearbeitet durch User
von F. H. (avrfreak)


Lesenswert?

Weil ich eine Matrix ansteuer und immer einer variable vorgibt welche 
leds leuchten müssen. Und eine Variable definiert eine reihe der Matrix. 
Ich kann das so aber nicht direkt ausgeben, da i die matrix auf schiebe 
registern habe und somit i die signale einzeln durchschiebe.

von Karl H. (kbuchegg)


Lesenswert?

F. H. schrieb:
> Weil ich eine Matrix ansteuer und immer einer variable vorgibt welche
> leds leuchten müssen.

Ah siehst du.
Dazu brauchst du den Wert eines Bits nicht in einer Variablen (und schon 
gar nicht in einer int Variablen! int willst du nicht benutzen, wenn es 
nicht sein muss. Wenn du mit 8 Bit durchkommst, dann nimmst du uint8_t 
oder int8_t und nicht das 16-Bit 'int')
1
   for( uint8_t i = 0; i < 8; i++ )
2
   {
3
     if( wert & 0x01 )
4
       Bit ist 1, mach was
5
     else
6
       Bit ist 0, mach was
7
8
    wert >>= 1;
9
  }

denn was du auf keinen Fall möchtest, ist ein
1
     .... & ( 1 << i )

in irrgend einer Form. Denn das ist ein teure Operation. Da schiebst du 
lieber einen Wert sukzessive um jeweils 1 Stelle nach rechts und testest 
immer auf das 0-te Bit

(oder schieben nach links und testen auf das 7-te Bit, wenn die 
Reihenfolge anders rum sein soll)

von F. H. (avrfreak)


Lesenswert?

Kann i das dann auch direkt so machen?
1
 for( uint8_t i = 0; i < 8; i++ )
2
   {
3
     if( wert & i )
4
       Bit ist 1, mach was
5
     else
6
       Bit ist 0, mach was
7
8
    wert >>= 1;
9
  }

von Karl H. (kbuchegg)


Lesenswert?

F. H. schrieb:
> Kann i das dann auch direkt so machen?


Das weiß ich nicht, ob du die Programmteile, die ich jetzt hier nicht 
ausgeführt habe, wie zb die Ansteuerung der Schieberegister, alleine 
hinkriegst.
Aber die Abarbeitung der einzelnen Bits in einem Byte, welches in 'wert' 
steht, die kannst du so machen - drum hab ich das ja aufskizziert, wie 
man das in so einer konkreten Situation macht.

von Peter II (Gast)


Lesenswert?

F. H. schrieb:
> Kann i das dann auch direkt so machen?

machen ja, aber etwas sinnvolles kommt dabei nicht raus.

von F. H. (avrfreak)


Lesenswert?

Ja danke
Nein das mit den Schieberegistern habe Ich schon.
Ich bin nur noch nicht ganz so vertraut mit C.

von Karl H. (kbuchegg)


Lesenswert?

F. H. schrieb:
> Kann i das dann auch direkt so machen?

ach jetzt seh ichs erst

>      if( wert & i )

Nein. Völlig falsch.
Wozu soll das gut sein?

Du scheinst nicht begriffen zu haben, was das Konzept ist.
Anstatt sich jeweils ein eigenes 'Fenster' zu machen, mit dem man einen 
Blick auf das i-te Bit erhascht, dreht man den Spiess um. Man macht 1 
immer gleiches Fenster und schiebt die Bits unter dem "Fenster" durch. 
Das ist nämlich für den µC einfacher, weil die Erzeugung des "Fensters" 
für einen AVR eine aufwändige Sache ist.
Im Endeffekt kommt aber beides aufs gleiche raus.

: Bearbeitet durch User
von Lutz H. (luhe)


Lesenswert?

Ist  der Speicher so knapp?
ich würde lieber 1 Byte für einen Matrixpunkt nehmen.
Das Bit hin und hergeschiebe ist zwar interessant, und manchmal 
sinnvoll.
Aber jeden Matrixpunkt mit einem Namen ansprechen zu können, ist für 
mich die einfachere Lösung. Dann bracht man nicht jedesmal so tolle 
Bitmanipulationen.

von F. H. (avrfreak)


Lesenswert?

Achso
Jetzt hab ich es verstanden.
deswegen auch das "wert >>= 1;"
Vielen Dank, jetzt machts Sinn.

von F. H. (avrfreak)


Lesenswert?

Sry bin in dieser Materie noch nicht ganz so durchgestiegen.
Deswegen frag ich ja auch nach.

von Karl H. (kbuchegg)


Lesenswert?

F. H. schrieb:
> Sry bin in dieser Materie noch nicht ganz so durchgestiegen.
> Deswegen frag ich ja auch nach.


Das Problem ist eigentlich, dass das hier noch der einfachste Teil der 
Ansteuerung einer Matrix ist.
Eine LED-Matrix ist nun mal kein Einsteigerprojekt, auch wenn es viele 
immer wieder dafür halten (und mir rätselhaft ist, was an einer kleinen 
LED-Matrix so toll sein soll - aber das muss jeder für sich entscheiden)

: Bearbeitet durch User
von J.-u. G. (juwe)


Lesenswert?

Damit es Dir später nicht noch auf die Füße fällt:

F. H. schrieb:
> also bei array[2] is das ja 0xEF

Nein. Gemäß Deines Eröffnungsbeitrags ist der Wert von array[2] gleich 
0xA3.

von F. H. (avrfreak)


Lesenswert?

Hab des jetzt mal versucht so umzusetzten mit der Bitmanipulation.
Allerdings kommt immer 0 raus
1
uint8_t iValue = 0b00000001
2
3
for(uint8_t i = 0; i < 8; i++){
4
    if(wert & 0x01)
5
       //Trifft niemals ein
6
    else
7
8
    iValue >>= 1;
9
}

von J.-u. G. (juwe)


Lesenswert?

F. H. schrieb:
> Allerdings kommt immer 0 raus
Woher weist Du das?

> if(wert & 0x01)
Wo kommt denn plötzlich die Variable "wert" her?

Du musst wohl etwas mehr Code zeigen.

von F. H. (avrfreak)


Lesenswert?

Sry so funktioniert es schon.
Nur sobald der Wert über einem bit ist
klappt es nicht mehr

: Bearbeitet durch User
von Sean G. (atmega318)


Lesenswert?

Möglicherweise währe es einfacher, wenn du die SPI Hardware benutzt für 
das Schieberegister. Dann kannst du nämlich deine ganze 8-Bit Variable 
mit dpi_fast_shift(deine_variable); übergeben.
Aus deinem Code werde ich leider überhaupt nicht schlau, aber hier die 
simpelste Variante (nicht optimiert) wie ich es machen würde:
1
  if (variable & 1)
2
  {
3
    //mach was
4
  }
5
        else
6
  {
7
    //mach was anderes
8
  }
9
  if (variable & 2)
10
  {
11
    //mach was
12
  }
13
        else
14
  {
15
    //mach was anderes
16
  }
17
  if (variable & 4)
18
  {
19
    //mach was
20
  }
21
        else
22
  {
23
    //mach was anderes
24
  }
und so weiter

: Bearbeitet durch User
von Lutz H. (luhe)


Lesenswert?

Mit Klammern  {}?

char iValue[8] = { 1, 0, 0, 0, 0, 0, 0, 1 };


  for (int i = 0; i < 8; i++){
    if (iValue[i] == 0)
    {

      iValue[0] <<= 1;
      ;
    }
    else
    {

      iValue[0] <<= 1;
      ;
    }
  }

von Karl H. (kbuchegg)


Lesenswert?

F. H. schrieb:
> Sry so funktioniert es schon.
> Nur sobald der Wert über einem bit ist
> klappt es nicht mehr

Dann zeig halt mal den RICHTIGEN Code.
Dann hilft dir auch jemand, all die kleinen blöden Fehler zu 
eliminieren, die du eingebaut hast.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Sean Goff schrieb:
> Aus deinem Code werde ich leider überhaupt nicht schlau, aber hier die
> simpelste Variante (nicht optimiert) wie ich es machen würde:

Das ist doch Quatsch
Wenn du mit einer Schleife nicht umgehen kannst, dann lass es und red 
nicht Anfängern so einen Unsinn ein.

SPI Hardware einzusetzen ist grundsätzlich ok.
Aber auch die 'händische' Ausgabe zu Fuss ist keine Raketentechnik und 
eine derartige Funktion ist in weniger als 14 Zeilen Code abgehandelt
1
void outputByte( uint8_t wert )
2
{
3
  for( uint8_t i = 0; i < 8; i++ )
4
  {
5
    if( wert & 0x01 )
6
      ein 1 Bit auf die Datenleitung schalten
7
    else
8
      ein 0 Bit auf die Datenleitung schalten
9
10
    Clock auf 1
11
    Clock auf 0
12
13
    wert >>= 1;
14
  }
15
}
(die Portoperationen müssen noch ausformuliert werden)

Bei einer Schieberegisterkette bestehend aus 595 Schieberegistern wird 
dann hinten nach, nachdem alle Bytes ausgegeben worden sind und somit 
die Schieberegister neu befüllt wurden, noch der Puls auf RCLK 
ausgegeben, damit die Schieberegister den neuen Inhalt auch auf die 
Ausgänge durchschalten.
1
void outputBytes( uint8_t byte1, uint8_t byte2, uint8_t byte3 )
2
{
3
  outputByte( byte1 );
4
  outputByte( byte2 );
5
  outputByte( byte3 );
6
7
  RCLK auf 1
8
  RCLK auf 0
9
}

SPI Hardware dafür lass ich mir gerne einreden. Aber eigentlich ist die 
ganze Sache so simpel, dass die jeder in 10 Minuten programmieren können 
muss. Und zwar auch dann, wenn ich ihn morgens um 4 aus dem Bett hole.

: Bearbeitet durch User
von F. H. (avrfreak)


Lesenswert?

Vielen dank aber die ausgabe habe ich schon längst.
Ich versuche nur noch schrift und "animationen" einzufügen.
Aber Trotzdem vielen Dank

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
Noch kein Account? Hier anmelden.