Forum: Mikrocontroller und Digitale Elektronik 3 byte zu 24 bit


von Björn (Gast)


Lesenswert?

Hallo zusammen,


ich lese mit einem MSP430F2232 über SPI einen analogen Spannungswert 
ein, der mit einem 24 bit AD-Wandler gemessen wurde.
Der AD-Wandler schickt nach Anfrage des Wertes 3 Bytes (Most 
significant-, Mid - und Least significant Byte). Zusammen also meine 24 
bit.
Mein Problem ist, ich weiß nicht (bin Anfänger), wie ich aus den 3 Bytes 
nun den Spannungsbetrag mache.

Im Moment versuche ich es mit folgendem Code (ich nutze IAR Kickstart):
 "ADS_RXTX(command);                       //send command
  value1=ADS_RXTX(0x00);                   //send clock
  value2=ADS_RXTX(0x00);                   //send clock
  value3=ADS_RXTX(0x00);                   //send clock

 big=value2 | (value3<<8) | ((unsigned long)value4<<16);"

"ADS_RXTX()" sendet die Anfrage an den AD-Wandler und gibt den Wert vom 
AD-Wandler zurück. "0x00" soll dann keine Nachricht schicken, sondern 
nur eine clock erzeugen, damit der AD-Wandler seine Werte schicken kann. 
Die 3 Bytes lege ich dann also in den Variablen value1, value2 und 
value3 (alle als "unsigned char" deklariert). Z.B. kommen dann folgende 
Werte in den Variablen vor:
value1: 0x18
value2: 0xFE
value3: 0x71

Daraus hätte ich gerne in der Variable big (deklariert als "unsigned 
long") den dezimalen Wert. Hier also 18FE71hex=1638001dec.

Hat jemand eine idee, wies funktioniert?


Vielen Dank,
Björn

von Timmo H. (masterfx)


Lesenswert?

1
long big;
2
unsigned char value1,value2,value3;
3
...
4
...
5
ADS_RXTX(command);                       //send command
6
value1=ADS_RXTX(0x00);                   //send clock
7
value2=ADS_RXTX(0x00);                   //send clock
8
value3=ADS_RXTX(0x00);                   //send clock
9
10
big = (value1<<16) | (value2<<8) | value3;
Geht zumindest bei mir.
evtl. auch noch etwas zur Sicherheit Casten
1
big = (unsigned long)(value1<<16) | (unsigned int)(value2<<8) | value3;

von Johannes M. (johnny-m)


Lesenswert?

Timmo H. wrote:
> evtl. auch noch etwas zur Sicherheit Casten
>
1
> big = (unsigned long)(value1<<16) | (unsigned int)(value2<<8) | value3;
2
>
Der erste cast ist bei einer 8- oder 16-Bit-Plattform i.d.R. immer 
erforderlich (bei allen Plattformen, in denen int nur 16 Bit lang 
ist), da das Schieben um 16 Stellen sonst ins Nirvana geht. Der zweite 
cast ist sinnvoll (ein einfaches unsigned dürfte aber reichen), da bei 
Schiebeoperationen bei signed-Werten die Vorzeichenbehandlung nicht 
festgelegt ist.

von holger (Gast)


Lesenswert?

>big = (unsigned long)(value1<<16) | (unsigned int)(value2<<8) | value3;

Ich würde das so machen

big = ((unsigned long)value1<<16) | ((unsigned int)value2<<8) | value3;

von Johannes M. (johnny-m)


Lesenswert?

holger wrote:
>>big = (unsigned long)(value1<<16) | (unsigned int)(value2<<8) | value3;
>
> Ich würde das so machen
>
> big = ((unsigned long)value1<<16) | ((unsigned int)value2<<8) | value3;
Da hast Du völlig Recht! Ich hatte die falsche Klammerung oben glatt 
übersehen. Die Werte müssen natürlich vor dem Schieben konvertiert 
werden!

von eProfi (Gast)


Lesenswert?

Ich würde das ganz ohne Schiebereien machen mit einer Union:
Einziger Nachteil: nicht ohne Prüfung auf andere Systeme (Endianess) 
übertragbar.

Vorteil: sehr schnell und kompakt
z.B. Beitrag "Re: 3 bytes in einen Datentyp"

Was lernen wir daraus: zuerst suchen, dann fragen.

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.