Forum: Compiler & IDEs Problem bei bit shifting


von Torsten W. (torsten_w)


Lesenswert?

Hi,

ich lese mit einem mega32 mittels SPI einen MCP2515 CAN-Controller aus 
wobei ich auf ein Problem beim zusammensetzten des Identifiers mittels 
bitweise Verschiebung stoße.
Und zwar handelt es sich dabei um einen Standart Identifier mit einer 
Länge von 10 bit, dessen Bits 3-10 ein eigenes Register für sich 
beanspruchen und den Bits 0-2, die sich ein anderes Register mit 
weiteren Daten teilen.
Nach dem einzelnen Auslesen (da das auslesen korrekt funktioniert hab 
ich sie hier mal hart rein geschrieben) setze ich diese mit folgendem 
Code zusammen:
1
  uint8_t part1 = 0b00100100;
2
  uint8_t part2 = 0b01100000;
3
4
  uint16_t id = ((uint16_t)(part1 << 3) | (uint16_t)(part2 >> 5));

part1 sollte durch die Verschiebung nach links ja '0b100100000' 
betragen. Genau hier liegt aber mein Problem, part1 beträgt nach der 
Verschiebung nämlich nur noch '0b100000', das höherwertige HIGH Bit geht 
also irgendwie verloren.
part2 wird korrekt zu '0b11' verschoben.
Durch dieses Problem mit part1 erhalte ich am Ende natürlich nicht den 
richtigen Wert, was ich mir aber nicht wirklich erklären kann.
Woran könnte das liegen? Ich hab das ganze auch noch auf meinem Rechner 
ausprobiert und dort kommt als korrektes Ergebnis '0b100100011' heraus.
Vergesse ich da irgendeine Eigenart des AVR, weswegen es darauf nicht 
klappt, auf meinem Desktop aber schon?

Gruß,
toti

von DerAlbi (Gast)


Lesenswert?

Untersuche mal bitte die Unterschiede dieser Codezeilen:

uint16_t id = ((uint16_t)(part1 << 3) | (uint16_t)(part2 >> 5));
uint16_t id = (((uint16_t)part1) << 3) | (((uint16_t)part2) >> 5);

Mmerkste was? Welchen Typ schiebst du bei deiner Zeile um 3 nach links?
Kann dieser Typ das Ergebnis aufnehmen? Bedenke: erst NACH dem schieben 
wird auf 16 bit gecastet.
Das Thema sollte geklärt sein.

von Torsten W. (torsten_w)


Lesenswert?

Danke für die schneller Antwort. Daran hab ich auch gedacht und beides 
vorher ausprobiert, aber leider kommt bei beiden das selbe Ergebnis 
heraus. Egal ob ich vorher in den 16bit Integer caste und dann schreibe 
oder erst schiebe und dann caste.

Gruß,
toti

von Stefan E. (sternst)


Lesenswert?

> Bedenke: erst NACH dem schieben wird auf 16 bit gecastet.

part1 wird aber vor dem Schieben nach int promotet.

> Das Thema sollte geklärt sein.

Nö.

@ Torsten W.:
Könnte es sein, dass du die Option -mint8 verwendest?

von Stefan E. (sternst)


Lesenswert?

Torsten W. schrieb:
> Genau hier liegt aber mein Problem, part1 beträgt nach der
> Verschiebung nämlich nur noch '0b100000', das höherwertige HIGH Bit geht
> also irgendwie verloren.

Wie stellst du das überhaupt fest?

von Torsten W. (torsten_w)


Lesenswert?

Hi,

ich gehe mal davon aus, dass du mit -mint8 eine Option des Compilers 
meinst oder? Die benutze ich auf jedenfall nicht.
Ich hab mir die Variablen mittels jtag und angeschaut und via serieller 
UART auf dem PC ausgegeben.

Gruß,
toti

von Stefan E. (sternst)


Lesenswert?

Nun, ich sehe nicht, wie die gezeigte Zeile der Schuldige sein könnte. 
Entweder sieht die Zeile in Wirklichkeit doch anders aus, oder es 
passiert danach noch was mit id. Oder du hast die 
Initialisierungszeilen für part1 und part2 nur als Beispiel gepostet, 
und in Wirklichkeit steht da schon nicht das drin, was drin sein sollte.

Oder anders gesagt: ohne den Original-Code (und zwar mehr als nur eine 
Zeile) kann dir hier nicht weiter geholfen werden.

von Torsten W. (torsten_w)


Lesenswert?

Hi,

der Fehler war genauso dumm wie einfach. Ich hab mir die Funktion, 
welche den Code binär über UART ausgibt gerade nochmal angeschaut und 
irgendwie ist da an einer stelle peinlicherweise eine 8 an die stelle 
einer 16 gerutscht, was die Ausgabe ab dem 8 Bit dann verfälscht hat. 
Ich hatte das testweise gemacht und durch ein "Undo" ausversehen wieder 
reingebracht.
Entschuldigt vielmals, dass ich damit eure zeit verschwendet habe und 
ein umso größeres Dankeschön für die vielen schnellen Antworten.

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.