Forum: Mikrocontroller und Digitale Elektronik Byte verbittet sich das Verbitten


von Stephan R (Gast)


Lesenswert?

Moin!

Ich versuche, ein über die serielle SS empfangenes Byte, was zuvor am 
Bildschirm auf acht Bits individuell zusammengestzt wurde und geschickt 
wurde, wieder in 8 Bits zu zerlegen.

Dazu verwende ich folgende, handwerklich liebevoll zurechtgeschusterte 
Funktion, jedoch kommen unsinnige Werte bei heraus. Die "gleiche" 
Funktion in VB6 funktioniert. Findet jemand einen Schreib-/Denkfehler? 
Falls es eine einfachere Lösung des Problems gibt.. bin für alles offen. 
Ausser für politische Kommentare.

Schönen Gruß- Stephan

//ersteinmal die Bits definieren ++++++++++++++++++++++++++++++++++++

struct
{
unsigned bit[10];
}x;

//dann meine Funktion +++++++++++++++++++++++++++++++++++++++++++++++

void byte_to_bit (char wert1)
{
int count;
  for(count = 1; count <= 8; count++)
  {
    if(wert1 > ((2 ^ (8 - count) )- 1))
    {
      x.bit[count-1] = 1;
      wert1 = wert1 - (2 ^ (8 - count));
    }
    else
    {
      x.bit[count-1] = 0;
    }
        }

}
//anschließend die "Auswertung"  +++++++++++++++++++++++++++++++++++++++

if (x.bit[1] == 1)           //Beispielhaft: beigesetztem Bit 1
{
  fan_on;               //Beispielhaft: fan einschalten
}
else
{
  fan_off;              //Beispielhaft: fan ausschalten
}

von Simon K. (simon) Benutzerseite


Lesenswert?

Hm. Die Funktion sieht komisch aus. Bits testet man üblicher weise mit 
dem boolschen AND-Operator.
Ansonste: Gib mal ein kompilierbares Beispiel und nicht so ein Schnipsel 
und das sogar ohne Syntax Highlighting.

von Karl H. (kbuchegg)


Lesenswert?

Stephan R schrieb:

>     if(wert1 > ((2 ^ (8 - count) )- 1))

^ ist in C die EXOR Operation und nicht 'hoch'

von Stephan R (Gast)


Lesenswert?

Ich bin gern bereit etwas Etabliertes zu verwenden.  Meinst Du Boolscher 
AND-Operator a´la Registerbits setzen? Kenn ich. Aber wie überträgt Mann 
das auf die Aubfrage von Bits einer char- variablen?

von Karl H. (kbuchegg)


Lesenswert?

Du machst das zu kompliziert.

Ein paar Anmerkungen:

  for(count = 1; count <= 8; count++)

in C wird bei 0 angefangen zu zählen! Das hat seinen guten Grund, viele 
Dinge werden einfacher, wenn man das tut.

Den Datentyp char reservierst du ausschliesslich für Texte bzw. 
Buchstaben. Für ein Byte nimmst du immer den Datentyp unsigned char bzw. 
uint8_t. Damit passieren dir dann keine seltsamen Dinge, wenn auf deinem 
Compiler ein char ein Vorzeichen hat.
1
void byte_to_bit (unsigned char wert1)
2
{
3
  unsigned char mask;
4
  unsigned char count;
5
6
  mask = 0x80;
7
8
  for( count = 0; count < 8; count++ )
9
  {
10
    if( wert1 & mask )
11
      x.bit[count] = 1;
12
    else
13
      x.bit[count] = 0;
14
15
    mask >>= 1;
16
  }
17
}

von Oliver J. (skriptkiddy)


Lesenswert?

Ich hätte das so gelöst.
1
void byte_to_bit (char wert1)
2
{
3
int count;
4
  for(count = 0; count < 8; count++)
5
  {
6
    x.bit[count] = (  wert & (1 << count)  )  >>  count;
7
  }
8
 }

von Karl H. (kbuchegg)


Lesenswert?

Stephan R schrieb:
> Ich bin gern bereit etwas Etabliertes zu verwenden.  Meinst Du Boolscher
> AND-Operator a´la Registerbits setzen?

nicht setzen.
Ein Bit wir dmit einer ODER Operation gesetzt.
Mit einem UND kann man Bits löschen (also gezielt auf 0 setzen).
Man kann daher ein UND dazu benutzen, alle nicht interessierenden Bits 
gezielt auf 0 zu setzen. Wenn dann etwas übrig bleibt, was nicht 0 ist, 
dann war an der interessierenden Stellen eine 1 :-)

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

von Simon K. (simon) Benutzerseite


Lesenswert?

Skript Kiddy schrieb:
> Ich hätte das so gelöst.
>
>
1
> void byte_to_bit (char wert1)
2
> {
3
> int count;
4
>   for(count = 0; count < 8; count++)
5
>   {
6
>     x.bit[count] = (  wert & (1 << count)  )  >>  count;
7
>   }
8
>  }
9
>

Ja, Karl Heinzes Methode ist aber besser. Bei dir wird in einer Zeile 
zwei mal um nicht-konstante Anzahl geshiftet. Das ist Langsam auf den 
meisten 8 Bit Prozessoren.
Dann lieber ein if/else. Auch wenn deine Methode auf den ersten Blick 
"schöner" aussieht.

von Stephan R (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> ^ ist in C die EXOR Operation und nicht 'hoch'

Tückisch! Drei Programmiersprachen aber nur ein Kopf.

Karl heinz Buchegger schrieb:
> in C wird bei 0 angefangen zu zählen!

Normal tu ich das, aber aus irgendeinem Grund, den ich nun nicht mehr 
finde, hatt ich ne Ausnahme gemacht...


Habt vielen dank, ich werd Eure Vorschläge mal austesten. Prost!

von Karl H. (kbuchegg)


Lesenswert?

Simon K. schrieb:

> Ja, Karl Heinzes Methode ist aber besser. Bei dir wird in einer Zeile
> zwei mal um nicht-konstante Anzahl geshiftet. Das ist Langsam auf den
> meisten 8 Bit Prozessoren.

Muss nicht sein.
Auf einem AVR ist sie das aber. Der AVR hat keine Assembler Instruktion 
für einen Bitshift mit einer variablen Anzahl an Stellen.

von Oliver J. (skriptkiddy)


Lesenswert?

Prost.

von Stephan R (Gast)


Lesenswert?

Alter!
Immer wenn mal wieder ein Lämpchen aus einem anderen, (von mir 
gewünschten Grund) angeht, denk ich: yeah, ich bin geil, C ist ein 
Klacks! Dann lässt hier wieder einer einen Kommentar los, dessen 
Vokabular mir nicht mal ganz klar ist, und ich fühl mich wie ein 
Dreijähriger beim Zahnriemenwechseln!

von Paul Baumann (Gast)


Lesenswert?

@Stephan R.

O.T.
Ich kann Dir zwar bei der Fehlersuche nicht helfen, weil ich kein
"C"
versteh.

Deinen Thread-Titel finde ich aber wirklich Spitze !
:-))
MfG Paul

von Eddy C. (chrisi)


Lesenswert?

Da geht doch noch was:
1
void byte_to_bit(unsigned char wert1)
2
{
3
  char count;
4
  for( count = 7; count >= 0; count--, wert1 >>= 1)
5
    x.bit[count] = wert1 & 1;
6
}

von Stephan R (Gast)


Lesenswert?

Danke, helfen brauchste auch nicht mehr, das Kernproblem ist gelöst.

Eine andere, weiterführende, notwendige Optimierung:

um die Bits schließlich in Aktionen umzusetzen (es wird eine Art 
Override- Steuerung: jeder durch den Controller gesteuerte Aktor muss 
per Bitwahl am Monitor, auch über den Kopf des uC heraus, beeinflusst 
werden können) gehe ich folgendermassen vor (bin nicht stolz drauf)

erst Definitionen definieren:

   #define motor1_on PORTD |= (1<<PD3);
   #define motor1_off PORTD &= ~(1<<PD3);


später alle auf einmal nacheinanderabfragen:


if (x.bit[0] == 1)
{
    fan_on
}
else
{
    fan_off
}

if (x.bit[1] == 1)
{
    fan_on
}
else
{
    fan_off
}


Das ist doch Kinderkacke. Wie tut Mann das?

von Eddy C. (chrisi)


Lesenswert?

So:
1
void SetFanPorts(void)
2
{
3
  unsigned char Count;
4
  unsigned char FanStatus = 0;
5
  for (Count = 0; Count < 8; Count++)
6
  {
7
    FanStatus <<= 1;
8
    FanStatus |= x.bit[Count];
9
  }
10
  PORTD = FanStatus;
11
}

von Stephan R (Gast)


Lesenswert?

Hab versucht, umzubauen aber bei mir siehts so aus: etwa 10 Bytes kommen 
rein und jedes Bit entspricht einem Schaltzustände an jeweils völlig 
unterschiedlichen Ports...! Etwas wirr...

von Oliver J. (skriptkiddy)


Lesenswert?

Simon K. schrieb:
> Bei dir wird in einer Zeile zwei mal um nicht-konstante Anzahl geshiftet. > Das 
ist Langsam auf den meisten 8 Bit Prozessoren.

Stimmt. Weil die Dinger soweit ich weiß keine Barrelshifter haben. Hab 
den Code deshalb auch nicht als effizient verkauft.

Gruß Skriptkiddy

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.