Forum: Mikrocontroller und Digitale Elektronik Bit Abfrage Bitmanipulation


von Chris (Gast)


Lesenswert?

Hallo,

ich möchte Abfragen ob ein bestimmter Bit gesetzt ist oder nicht. Den 
Artikel zu Bitmanipulation habe ich gelesen, doch leider hilft er mir 
nicht genau weiter.

Ich habe folgenden Code
1
#define RF_ACK1      0x04
2
  #define RF_ACK2    RF_ACK1 | 0x00
3
  #define RF_ACK3    RF_ACK2 | 0x01
4
  #define RF_ACK0    RF_ACK2 | 0x01
5
6
if(RF_ACK3 & RF_ACK0)    // soll true
7
   i2clcd_printlr(1,1,"if 1");
8
       
9
if(RF_ACK2 & RF_ACK3)    // soll false
10
   i2clcd_printlr(2,1,"if 2");

Nun bekomme ich für beide IF's ein true. Leider nicht genau das, was ich 
erwarte. Denn RF_ACK3 ist nicht RF_ACK0, also ertwarte ich ein false. 
Was genau mache ich falsch und wie löse ich es am besten.

von Wanzenprofi (Gast)


Lesenswert?

> RF_ACK3 & RF_ACK0

Mach das, was der Präprozessor auch macht: Text ersetzen und schauen, 
was dabei rauskommt...

von Karl H. (kbuchegg)


Lesenswert?

Chris schrieb:

> Nun bekomme ich für beide IF's ein true.

Jep.
Der Ausdruck wird ausgewertet und wenn da etwas ungleich 0 herauskommt, 
dann gilt das als TRUE

> erwarte. Denn RF_ACK3 ist nicht RF_ACK0

Dein Vergleich ist ja auch nicht auf Gleichheit. Du verundest 2 Zahlen.

> Was genau mache ich falsch und wie löse ich es am besten.

Spiel Präprozessor und mach die Textersetzung. Da bleibt dir dann ein 
Ausdruck über in dem nur noch Zahlen und Verknüpfungen vorkommen. Den 
wertest du dann mal händisch aus. Und dann macht es irgendwann klack und 
du verstehst, die dein Egrebnis zu Stande kommt.

   if(RF_ACK3 & RF_ACK0)


Textersetzung:  Statt RF_ACK3  setzt du den Text RF_ACK2 | 0x01 ein


  if (RF_ACK2 | 0x01 & RF_ACK0)

nächste Textersetzung: statt RF_ACK0 setzt du den Text RF_ACK2 | 0x01 
ein

  if (RF_ACK2 | 0x01 & RF_ACK2 | 0x01)

nächste Textersetzung: anstelle von RF_ACK2 setzt du RF_ACK1 | 0x00 ein

  if (RF_ACK1 | 0x00 | 0x01 & RF_ACK1 | 0x00 | 0x01)


nächste Textersetzung: anstelle von RF_ACK1 setzt du 0x04 ein

  if (0x04 | 0x00 | 0x01 & 0x04 | 0x00 | 0x01)

und jetzt wertest du den Ausdruck mit den C Regeln aus. Was kommt raus?

von Duck und weg (Gast)


Lesenswert?

Chris schrieb:
> Nun bekomme ich für beide IF's ein true. Leider nicht genau das, was ich
> erwarte.

Das blöde ist, dass Computer immer das machen, was man ihnen sagt und 
nicht unbedingt das, was man erwartet.

von Chris (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> und jetzt wertest du den Ausdruck mit den C Regeln aus. Was kommt raus?

ich weiß nicht genau was du mit C Regeln meinst.

Bekomme if(0x05 & 0x05) oder halt (101 & 101)

von Karl H. (kbuchegg)


Lesenswert?

Chris schrieb:
> Karl Heinz Buchegger schrieb:
>> und jetzt wertest du den Ausdruck mit den C Regeln aus. Was kommt raus?
>
> ich weiß nicht genau was du mit C Regeln meinst.
>
> Bekomme if(0x05 & 0x05) oder halt (101 & 101)

Und?
Was ist das Ergebnis wenn du die beiden verundest?

von Erich (Gast)


Lesenswert?

Ja, das ist quasi die Fortführung von
Beitrag "C: Funktion mit #define als Platzhalter"

Immer tüchtig  #define  hinschreiben, damit man schon nach ein paar 
Codezeilen (selbst) nimmer durchsteigt !

Und unbedingt auch immer die Klammern weglassen, besonders wenn 
unterschiedliche Operatoren im Spiel sind.

von Chris (Gast)


Lesenswert?

wenn ich das richtig mache ist es 0b101.

Karl Heinz Buchegger schrieb:
> Der Ausdruck wird ausgewertet und wenn da etwas ungleich 0 herauskommt,
>
> dann gilt das als TRUE

OK ich verstehe warum es nun true liefert. Wie genau muss ich nun 
abfragen, damit es nur true liefert, wenn die Bits gesetzt sind?

von Chris (Gast)


Lesenswert?

Erich schrieb:
> Immer tüchtig  #define  hinschreiben, damit man schon nach ein paar
>
> Codezeilen (selbst) nimmer durchsteigt !
>
> Und unbedingt auch immer die Klammern weglassen, besonders wenn
>
> unterschiedliche Operatoren im Spiel sind.

Mein Code ist länger !!!
Sollte oben nur mein Problem erläutern. Und welche Klammern vermisst du, 
damit du auch produktives zum Thema schreiben kannst?

von Chris (Gast)


Lesenswert?

ich sehe gerade, dass ich oben ein Fehler gemacht habe. Sollte lautern:
1
#define RF_ACK1      0x04
2
  #define RF_ACK2    RF_ACK1 | 0x00
3
  #define RF_ACK3    RF_ACK1 | 0x01
4
  #define RF_ACK0    RF_ACK1 | 0x01

von Karl H. (kbuchegg)


Lesenswert?

Chris schrieb:
> wenn ich das richtig mache ist es 0b101.
>
> Karl Heinz Buchegger schrieb:
>> Der Ausdruck wird ausgewertet und wenn da etwas ungleich 0 herauskommt,
>>
>> dann gilt das als TRUE
>
> OK ich verstehe warum es nun true liefert. Wie genau muss ich nun
> abfragen, damit es nur true liefert, wenn die Bits gesetzt sind?

Wenn welche Bits gesettz sind?
Wo sind diese Bits gesetzt?

Bis jetzt sind das alles ja nur konstante Zahlen. Da kannst du 
genausogut auch

  if( 1 )

hinschreiben


PS:
Bist du sicher, dass

  #define RF_ACK3    RF_ACK1 | 0x01
  #define RF_ACK0    RF_ACK1 | 0x01

RF_ACK3 und RF_ACK0 exakt die gleiche Binärdarstellung haben sollen? 
Wenn ja: Wazu gibt es dann RF_ACK3 überhaupt?

von Karl H. (kbuchegg)


Lesenswert?

Chris schrieb:
> Erich schrieb:
>> Immer tüchtig  #define  hinschreiben, damit man schon nach ein paar
>>
>> Codezeilen (selbst) nimmer durchsteigt !
>>
>> Und unbedingt auch immer die Klammern weglassen, besonders wenn
>>
>> unterschiedliche Operatoren im Spiel sind.
>
> Mein Code ist länger !!!

umso schlimmer.
Was bei kurzen Programmen unter Zusammenkneifen aller Augen (inklusive 
Hühneraugen) noch angehen mag, ist bei längeren Programmen der 
Dolchstoss in den Rücken des Programmierers.

> Sollte oben nur mein Problem erläutern. Und welche Klammern vermisst du,
> damit du auch produktives zum Thema schreiben kannst?

Denk mal über folgendes nach
1
#define TWICE(x)  2*x
2
3
...
4
  int i = 5;
5
  int j = TWICE( i + 3 );
welchen Wert hat j?
Ist das intuitiv? Würde man diess Ergebnis erwarten, wenn man das Makro 
nicht kennt und nur den Makronamen weiß?


Weiters denke über folgendes nach
1
#define ADD_TWO(x)  x+2
2
3
...
4
  int i = 5;
5
  int j = 2 * ADD_TWO( i )
Welchen Wert hat j?
Ist das intuitiv? Würde man diess Ergebnis erwarten, wenn man das Makro 
nicht kennt und nur den Makronamen weiß?

von Stefan T. (Gast)


Lesenswert?

Ja das mit den Konstanten war schon soweit richtig, ich wollte nur eine 
kleine Testumgebung. Zusammengefasst sollte es so aussehen
1
#define RF_T      0x04
2
  #define RF_ACK_YES    RF_T | 0x00    // 0b00000100
3
  #define RF_ACK_NO    RF_T | 0x01    // 0b00000101
4
5
if(0b00100100 & RF_ACK_YES)    // soll true
6
   i2clcd_printlr(1,1,"if t");
7
       
8
if(0b00100100 & RF_ACK_NO)    // soll false
9
   i2clcd_printlr(2,1,"if .");

Der Wert 0b00100100 wird übergeben und nun geprüft ob bits RF_ACK_YES 
oder ob RF_ACK_NO gesetzt sind.

Hoffe es ist nun verständlich.

von Karl H. (kbuchegg)


Lesenswert?

Stefan T. schrieb:
> Ja das mit den Konstanten war schon soweit richtig, ich wollte nur eine
> kleine Testumgebung. Zusammengefasst sollte es so aussehen
>
>
1
> #define RF_T      0x04
2
>   #define RF_ACK_YES    RF_T | 0x00    // 0b00000100
3
>   #define RF_ACK_NO    RF_T | 0x01    // 0b00000101
4
> 
5
> if(0b00100100 & RF_ACK_YES)    // soll true
6
>    i2clcd_printlr(1,1,"if t");
7
> 
8
> if(0b00100100 & RF_ACK_NO)    // soll false
9
>    i2clcd_printlr(2,1,"if .");
10
>
>
> Der Wert 0b00100100 wird übergeben und nun geprüft ob bits RF_ACK_YES
> oder ob RF_ACK_NO gesetzt sind.

Welches ist das Bit RF_ACK_YES?

Die beiden Konstanten

>   #define RF_ACK_YES    RF_T | 0x00    // 0b00000100
>   #define RF_ACK_NO    RF_T | 0x01    // 0b00000101

müssen sich ja in 2 Bits unterscheiden.
In der einen Konstante ist das eine Bit gesetzt und das andere gelöscht
und in der anderen Konstante genau umgekehrt

Aber bei deinen Konstanten ist das nicht so

Da ist nur das Bit 0 unterschiedlich
Ist es gesetzt, dann: NO
ist es gelöscht, dann: YES

aber mehr kann ich aus dem nicht herauslesen. Insbesondere ergibt diese 
Frage
> ob bits RF_ACK_YES
> oder ob RF_ACK_NO gesetzt sind.
keinen Sinn, weil es nun mal kein spezifisches Bit für YES gibt, welches 
gesetzt sein könnte.

von Karl H. (kbuchegg)


Lesenswert?

Ich denke, deine Fragestellung stimmt schon von Anfang an nicht.

Du willst gar nicht wissen, ob irgendwelche Bits gesetzt sind oder 
nicht.

Was du wissen willst: Wenn man einen Wert so manipuliert, dass nur die 
untersten 4 Bits übrig bleiben und alle anderen 0 sind, bleibt dann der 
Wert RF_ACK_YES bzw der Wert RF_ACK_NO übrig. Oder anders ausgedrückt: 
Welchen Wert aus deinen möglichen Werten ist in den untersten 4(?) Bits 
kodiert


   if( ( Wert & 0x0F ) == RF_ACK_YES )
     ....


   if( ( Wert & 0x0F ) == RF_ACK_NO )
     ....



oder auch

   switch ( Wert & 0x0F ) {

     case RF_ACK_YES:
       ....
       break;

     case RF_ACK_NO:
       ....
       break;


Alles in allem wieder mal ein Musterbeispiel dafür, dass man am besten 
hier im Forum von Anfang an die Karten auf den Tisch legt und nicht um 
den heißen Brei herumredet mit Analogieprogrammen die dann ganz was 
anderes zeigen als das Problem, das man eigentlich hat.
Es ist immer gut mit einer exakten Problemstellung zu fragen, anstelle 
Hilfe zu einer Lösung zu suchen, die von Anfang an gar nicht dazu 
geeignet ist das eigentliche Problem zu lösen.

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.