Bits aus Variable lesen

OP #3462989
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.
#3463045
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.
#3463061
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.
#3463115
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.
OP #3463122
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.
#3463143
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)
#3463154
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.
#3463162
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.
#3463169
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.
#3463196
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)
#3463359
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
#3463708
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren