Forum: Mikrocontroller und Digitale Elektronik Bitweiser Schiebeoperator über 8 stellen


von pszy (Gast)


Lesenswert?

Hallo,
Ich habe im EEPROM 4 Bytes, die ich in eine Variable vom Typ unsigned 
long speichern muss.
Dazu habe ich folgenden Code geschrieben:
1
unsigned long epoch = 0;
2
3
epoch = (EEPROM.read(1) << 24);
4
epoch += (EEPROM.read(2) << 16);
5
epoch += (EEPROM.read(3) << 8);
6
epoch += (EEPROM.read(4));

In der variable steht jetzt aber immer statt z.b. 4F11A2D5 der wert 
FFFFA2D5. Warum? Die Daten sind im eeprom auf jeden Fall 
richtigbabgelegt und werden auch korrekt ausgelesen.

Grüße
von na sowas (Gast)


Lesenswert?

Mein Tipp: vor dem Schieben kommt das Casten...
von pszy (Gast)


Lesenswert?

Vielleicht sollte ich noch erwähnen, dass ich einen atmega328 verwende
von pszy (Gast)


Lesenswert?

Die Antwort war ja schnell :)

Wie genau gehts das denn in meinem Fall? Ich habe so probiert:
1
epoch = static_cast<unsigned long> (EEPROM.read(1) << 24);
Compiler hat nicht gemeckert. Funktionieren tuts dennoch nicht.
von Chris H. (hergi)


Lesenswert?

probier mal so:
1
unsigned long epoch = 0;
2
3
epoch = (((unsigned long)EEPROM.read(1)) << 24);
4
epoch += (((unsigned long)EEPROM.read(2) << 16);
5
epoch += (((unsigned long)EEPROM.read(3) << 8);
6
epoch += (((unsigned long)EEPROM.read(4));
von pszy (Gast)


Lesenswert?

Danke Chris!
Bis dass da ein paar Klammern fehlten hat es so funktioniert :)

Grüße
von marcus6100 (Gast)


Lesenswert?

Nimm lieber uint32_t anstatt unsigned long. Das ist deutlicher.

Auch wenn der Compiler den Aufwand der Addition vermutlich wegoptimiert 
solltest du | benutzen.

Die Verwendung einer Addition um bitweise einen Wert zusammenzusetzen 
ungewöhnlich. Die Operator Precedence von bitwise or passt mit addition 
auch nicht zusammen.

Die Operator precedence ist:
erst: typecast
dann: addition
dann: bitwise shift
dann: bitwise or

Du kannst das also ohne die ganzen Klammern auch so schreiben:
1
uint32_t epoch;
2
epoch = (uint32_t)EEPROM.read(1) << 24
3
        | (uint32_t)EEPROM.read(2) << 16
4
        | (uint16_t)EEPROM.read(3) << 8
5
        | EEPROM.read(4);
6
7
oder:
8
epoch = (uint32_t)EEPROM.read(1) << 24 | (uint32_t)EEPROM.read(2) << 16 | (uint16_t)EEPROM.read(3) << 8 | EEPROM.read(4);
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

marcus6100 schrieb:
> Nimm lieber uint32_t anstatt unsigned long. Das ist deutlicher.
Ähm...
Kannst du das mal begründen?
von Peter D. (peda)


Lesenswert?

marcus6100 schrieb:
> Auch wenn der Compiler den Aufwand der Addition vermutlich wegoptimiert
> solltest du | benutzen.

Macht der AVR-GCC nicht.
Aber der OR-Code ist noch umständlicher (größer).
Der AVR-GCC ignoriert alle Codetextoptimierungen hartnäckig.


Peter
von Oo0 (Gast)


Lesenswert?

Lothar Miller schrieb:
> marcus6100 schrieb:
>> Nimm lieber uint32_t anstatt unsigned long. Das ist deutlicher.
> Ähm...
> Kannst du das mal begründen?

uint32_t ist ein 32 Bit Integer ohne Vorzeichen. unsigned long ist von 
der Plattform abhaengig in der Laenge, ohne Vorzeichen.

Da im EEPROM 4 Byte abgespeichert sind die einen Integer-Wert abbilden, 
ist es durchaus sinnvoll, einen dazu passenden Datentyp zu verwenden und 
erst anschliessend in den im Programm verwendeten Typ zu konvertieren. 
Was im Idealfall sowieso wegfaellt.
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.