Wie uint16_t bitweise verarbeiten

#3357073
Lesenswert?

Hallo,

ich versuche eine uint16_t Variable bitweise abzutasten und über einen 
Port zu einem andern AVR zu senden. Irgendwie passt das ausgegebene 
Bitmuster nicht zu dem was ich erwarte.

Habe ich einen Denkfehler?

Ich vermute den Fehler beim if-Vergleich.
Ich möchte durch den if-Vergleich herausfinden, ob das geweilige Bit in 
der sbyte-Variable gesetzt ist.


1
void sendebyte(uint16_t sbyte)
2
  {
3
  DDRB=0x01; //schaltet den PIN auf Ausgang
4
  uint16_t Vergleich=32768; //Schiebevariable auf Bit15 setzen
5
  uint8_t BitCount = 0;
6
  for (BitCount=0;BitCount<16;BitCount++)
7
    {
8
      if(Vergleich&sbyte)
9
        puls(); //sendet langen Impuls
10
      else
11
        pause(); //sendet kurzen Impuls
12
    Vergleich=Vergleich/2; //schiebt das Bit das nächste Bit
13
    }
14
  DDRB=0x00; //schaltet den PIN wieder auf Eingang
15
  }
Persönliche Seite #3357086
Lesenswert?

Nö, das ist soweit korrekt.

Allerdings kann man das auch ein bisschen anders schreiben:
1
uint16_t Vergleich = 1 << 15;
2
uint8_t BitCount = 0;
3

4
for (BitCount = 0; BitCount < 16; BitCount++)
5
{
6
  if (Vergleich & sbyte)
7
    puls(); //sendet langen Impuls
8
  else
9
    pause(); //sendet kurzen Impuls
10
  Vergleich >>= 1;
11
}

Inhaltlich ist das aber exakt das gleiche, es wird nacheinander Bit 15 
bis Bit 0 von "sbyte" untersucht und entsprechend "puls" oder "pause" 
aufgerufen.

Nur am Rande:
Der Variablenname "sbyte" ist ungeschickt gewählt.
Gast #3357155
Lesenswert?

Rufus Τ. Firefly schrieb:
> Allerdings kann man das auch ein bisschen anders schreiben:

Seh ich auch so:

Vergleich = 1<<15;
while (Vergleich)
{ if (Vergleich & sbyte)
    puls(); //sendet langen Impuls
  else
    pause(); //sendet kurzen Impuls
  Vergleich >>= 1;
}


Oder?

Nebenbei kann ich sowas leiden wie die Pest:
Rufus Τ. Firefly schrieb:
> uint16_t Vergleich = 1 << 15;

Schreib lieber
uint16_t Vergleich;

...
 Vergleich = 1<<15;
 while (....

Glaub's mir, der Compiler macht schon das Richtige draus, ohne daß es im 
Code aufträgt. Es ist ne Sache der Vermeidung von Schusselfehlern, 
direkt vor der Verwendung seine Schleifenvariable zu setzen, weil man 
sonst gar zu häufig bei etwas längeren Funktionen selbiges vergißt (Ich 
hab's ja ganz oben schon gemacht..)


W.S.
Gast #3357212
Lesenswert?

Mit Atmel habe ich nix am Hut, aber im Prinzip würde ich so vorgehen:

for (i=0;i<16; i++)
{
  Portpin = 0;
  pause (Zeit nach Wunsch)
  Portpin = Variable & 0x0001;
  Variable>>1;
  pause (Zeit nach Wunsch - 2 OPs)
}

Das ganze geht natürlich auch MSB first:

...
  Portpin = Variable & 0x800;
  Variable <<1;
...

Sauberer ist es das Ganze in einen Timer zu schicken, welcher exakt die 
Flanken generiert.
#3357781
Lesenswert?

Ich würds so machen:
1
for(int8_t i=15; i>=0; i-=1)
2
  (sbyte & (1<<i)) ? puls() : pause();
Ich weis, dass viele Leute das ? nicht so toll finden, aber ich finde es 
bei sehr kurzen Codesequenzen übersichtlicher als auf vier Zeilen 
gestreckt.

Und wer kein >=c99 verwendet, muss das int8_t vor die for-schleife 
setzen.


W.S. schrieb:
> sowas leiden wie die Pest:
> Rufus Τ. Firefly schrieb:
>> uint16_t Vergleich = 1 << 15;
>
> Schreib lieber
> uint16_t Vergleich;
>
> ...
>  Vergleich = 1<<15;
>  while (....
Genau das versuche ich zu vermeiden, da man sonst möglicherweise 
ausversehen die Variable benutzt bevor man sie initialisiert hat. Und je 
nach dem was vorher im RAM stand, bekommt man schwer reproduzierbare 
Ergebnisse.

> Es ist ne Sache der Vermeidung von Schusselfehlern,
> direkt vor der Verwendung seine Schleifenvariable zu setzen, weil man
> sonst gar zu häufig bei etwas längeren Funktionen selbiges vergißt (Ich
> hab's ja ganz oben schon gemacht..)
Ich deklariere meine Variablen erst dort, wo ich sie benötige, 
idealerweise im Schleifenkopf selbst. Nervt, wenn man wieder zum 
Funktionsanfang scrollen muss, nur um nachzusehen, ob die Variable jetzt 
ein int8_t oder ein uint8_t war. Und schön aussehen tut so ein 
Variablenblob am Anfang auch nicht.
#3358050
Lesenswert?

Simon S. schrieb:
> Ich würds so machen:for(int8_t i=15; i>=0; i-=1)
>   (sbyte & (1<<i)) ? puls() : pause();
> Ich weis, dass viele Leute das ? nicht so toll finden, aber ich finde es
> bei sehr kurzen Codesequenzen übersichtlicher als auf vier Zeilen
> gestreckt.

Ist ganz nett, aber man muss sich bewusst sein, dass der erzeugte Code 
je nach Architektur nicht unbedingt ideal wird. Auf einem AVR wird das 
(1 << i) mangels Barrel-Shifters nicht unbedingt performant.

Gruß
Marius

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