Forum: Mikrocontroller und Digitale Elektronik Probleme beim shiftleft


von bob b. (blobbob)


Lesenswert?

Hallo Forum, ich hab mal wieder eine Frage,

und zwar spreche ich einen Flashspeicher mit einem MSP430 an.
Der Speicher hat Adressen mit einer Länge von 3Bytes.
Über UART bekomme ich von extern Leseanfragen mit den Adressen die der 
MSP lesen soll.

Also bekomme ich ja die Adressen als 3 einzelne Bytes.
Im C-Code brauch ich die Adresse aber als eine Variable(nicht 3).
Wollte sie durch shift left zusammenbauen, also etwa so:

adresse  = (add[1] *65536) | (add[2]*256) | add[3];

adresse ist eine unsigned long int, und ich erwarte nach dem shiften 
sowas wie 0x00FFFFFF.

Allerdings bekomm ich falsche Adressen raus, sobald add[2] größer als 
0x79 ist.
add[1] und 3 allerdings können ohne Probleme 0xFF sein.

drei Beispiele:
adresse  = (0x00 *65536) | (0x79*256) | 0x00;
-->adresse = 0x00007900 <--Richtig

adresse  = (0x00 *65536) | (0x80*256) | 0x00;
--> adresse = 0xFFFF8000 <--Falsch

adresse  = (0xff *65536) | (0x79*256) | 0xff;
--> adresse = 0x00FF79FF <--Richtig

wo genau liegt denn hier das Problem, und wie kann ich das umgehen?

mfG

von Ralf G. (ralg)


Lesenswert?

0x79 * 256 = 127 * 256 = 32512
0x80 * 256 = -128 * 256 = -32768

bob blob schrieb:
> wie kann ich das umgehen?
Datentypen auf 32Bit erweitern. (Cast der Variablen oder L an die 
Konstanten)

von bob b. (blobbob)


Lesenswert?

danke Dir, aber warum macht das hier in dem Beispiel bei add[1] nichts 
aus, es ist ja höherwertiger als add[2]?
Kann ich bei einem 16bit Controller denn die datentypen überhaupt auf 32 
bit erweitern?

von (prx) A. K. (prx)


Lesenswert?

bob blob schrieb:

> danke Dir, aber warum macht das hier in dem Beispiel bei add[1] nichts
> aus, es ist ja höherwertiger als add[2]?

Weil 65536 nicht in "int" passt und daher ein "long" ist.

> Kann ich bei einem 16bit Controller denn die datentypen überhaupt auf 32
> bit erweitern?

Ja.

von (prx) A. K. (prx)


Lesenswert?

Apropos 3 Bytes: C Arrays fangen mit 0 an.

von bob b. (blobbob)


Lesenswert?

Ja im Array stehen noch andere, nicht für das Problem relevante, Sachen. 
Z.B. auch in add[0] ;)

Wie genau kann ich denn eine 32bit Variable erstellen?
Ich benutze die IAR Embedded Workbench IDE.

von (prx) A. K. (prx)


Lesenswert?

Es gibt C Lehrbücher. Und es gibt Doku von IAR.

von bob b. (blobbob)


Lesenswert?

Ouh, vielen dank ... .
BTW eine unsigned int long ist doch 4Byte, also 32 bit

von Ralf G. (ralg)


Lesenswert?

bob blob schrieb:
> Ouh, vielen dank ... .
> BTW eine unsigned int long ist doch 4Byte, also 32 bit
Das Ergebnis, aber nicht die Zwischenschritte, die werden mindestens 
in 'int' ausgeführt.
Zusammenfassung:
low-Byte -> alles in 'int' umgewandelt -> kein Problem, da wird ja 
nichts gerechnet, deshalb interessierts nicht weiter wenn 0x80 
eigentlich -128 ist
mid-Byte -> alles in 'int' umgewandelt -> ab 0x80 wirds negativ, weil 
der Compiler das Byte als -128 ansieht
high-Byte -> alles in 'int' umwandeln geht nicht, da 65536 schon 'long' 
ist

_->_ 256L sollte das Problem beheben

von bob b. (blobbob)


Lesenswert?

Dankeschön, die Erklärung leuchtet ein.
Aber entweder haperts gerade an der Syntax, oder ich muss dafür noch 
einen zusätzlichen Header einbinden.

von bob b. (blobbob)


Lesenswert?

Ok, das mit dem "_->_ 256L" hat ich ja so meine Probleme ;)
Aber mit der Erklärung, dass die Zwischenschritte in int und nicht long 
int gemacht werden, konnte ich das Problem scheinbar anderweitig lösen.

unsigned int msb = 0xff;
unsigned int mid = 0xee;
unsigned int lsb = 0xdd;
unsigned long int adresse;

mid = mid*256 | lsb;
startadresse = msb*65536 | mid;

--> adresse = 0x00FFEEDD

somit wird das mittlere Byte nicht über die Grenzen des ints verschoben.

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.