Forum: Mikrocontroller und Digitale Elektronik Aus 2 char ein unsigned int erzeugen


von Sebastian (Gast)


Lesenswert?

Hallo @ all

Ich möchte Daten von den Ports einlesen. Der Datenbus ist 8 Bit breit. 
Zuerst übertrage ich das Low-Byte und anschließend das High-Byte. Danach 
möchte ich das Low-Byte und High-Byte zusammenfassen zu einem unsigned 
int. Hier mein Quellcode:

bit status;
char low_byte, high_byte;


if(status == LOW_BYTE)
{
   low_byte = PINC;
   status = HIGH_BYTE;
}
else
{
   high_byte = PINC;

   ptr_datenpuffer[i] = high_byte;
   ptr_datenpuffer[i] = ptr_datenpuffer[i] << 8;
   ptr_datenpuffer[i] = low_byte;

   status = LOW_BYTE;
}

Ich dachte das durch die Wertzuweisung die unteren 8 Bits des unsigned 
int beschrieben werden. Anschließend wollte ich das ganze um 8 Stellen 
nach links schieben und dann das Low-Byte zuweisen. Dies scheint so aber 
nicht zu funktionieren

Grüsse

Sebastian

von Obelix (Gast)


Lesenswert?

Du überschreibst den wert damit.
x=(hi << 8) + lo;

von Sebastian (Gast)


Lesenswert?

Ist x=(hi << 8) + lo; denn die Lösung?

von Rahul D. (rahul)


Lesenswert?

>   ptr_datenpuffer[i] = high_byte;
>   ptr_datenpuffer[i] = ptr_datenpuffer[i] << 8;
>   ptr_datenpuffer[i] = low_byte;

Oder einfacher und kürzer:

ptr_datenpuffer[i] = ((int) high_byte )<<8) | low_byte;

von Obelix X. (obelix)


Lesenswert?

@Sebastian : ja, aber schau dir noch mal das Beispiel von Rahul an. 
(Typenumwandlung)


x=((unsigned int)hi << 8) + lo;

von Tobias R. (tobiasrohde)


Lesenswert?

oder so:

union{ unsigned short u_s;
       char u_c[2];
     }convert_var;

convert_var.u_c[0]=byte_1;
convert_var.u_c[1]=byte_2;

Ergebniss:

convert_var.u_s;

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Die Lösung mit der Union ist kein sauberes C, weil man je nach 
Compiler/Prozessor verschiedene Ergebnisse bekommen kann (Stichwort 
Endianness), deshalb sollte man lieber Shifts verwenden.

von Sebastian (Gast)


Lesenswert?

ptr_datenpuffer[i] = (((int) high_byte )<<8) | low_byte;

Wieso muss der Datentyp vom low_byte nicht verändert werden? Schließlich 
führe ich doch eine Veroderung von zwei unterschiedlichen Datentypen 
durch.

Grüsse

Sebastian

von Lötnagel (Gast)


Lesenswert?

Vorschlag: ausschießlich unsigned verwenden, zb so:
1
bit status;
2
unsigned char low_byte, high_byte;
3
4
// unsigned short ptr_datenpuffer[300];
5
6
if(status == LOW_BYTE)
7
{
8
   low_byte = PINC;
9
   status = HIGH_BYTE;
10
}
11
else
12
{
13
   high_byte = PINC;
14
   ptr_datenpuffer[i] = (high_byte<<8)+low_byte;
15
   status = LOW_BYTE;
16
}

  

von Sebastian (Gast)


Lesenswert?

Wieso braucht man denn mit einmal keine Typenumwandlung mehr?

von Lötnagel (Gast)


Lesenswert?

>Wieso braucht man denn mit einmal keine Typenumwandlung mehr?

Das erledigt der Compiler. Unsigned char und unsigned short haben
ja schon den gleichen Typ, nur unterschiedliche Größe.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Hi,

wie wärs mit


int intvalue=0;
char *low_byte = (char*) &intvalue;
char *high_byte = (char*) (&intvalue)+1;

Schneller gehts nicht, weil hier nicht gerechnet werden muss. Die ARMs 
haben idR. nen Barrelshifter drin, so dass man da in einem Takt bis zu 
32Bit shiften kann. Die AVRs glaub ich nicht...


Greetz,
/th.

von Sebastian (Gast)


Lesenswert?

Ich habe mich jetzt für diese Lösung entschieden

(((int) high_byte )<<8) | low_byte;

Vielen Dank für die Antworten. Es war sehr Aufschlußreich

Grüsse

Sebastian

von Johannes M. (johnny-m)


Lesenswert?

Sebastian wrote:
> Ich habe mich jetzt für diese Lösung entschieden
>
> (((int) high_byte )<<8) | low_byte;
Das kann aber auch nach hinten losgehen. Schiebeoperationen sollte man 
möglichst nur mit vorzeichenlosen Datentypen machen.

von Willi W. (williwacker)


Lesenswert?

wieso castest Du nach int, Du wolltest doch eigentlich unsigned?

von Sebastian (Gast)


Lesenswert?

Mein Fehler im Quellcode habe ich natürlich

ptr_datenpuffer[i] = (((unsigned int) high_byte )<<8) | low_byte;

benutzt

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Thorsten De buhr wrote:
> int intvalue=0;
> char *low_byte = (char*) &intvalue;
> char *high_byte = (char*) (&intvalue)+1;

Auch das ist nicht portabel. Je nach Prozessor kann es sein dass das 
low_byte hier gar nicht das low byte ist, sondern das high byte.

> Schneller gehts nicht, weil hier nicht gerechnet werden muss. Die ARMs
> haben idR. nen Barrelshifter drin, so dass man da in einem Takt bis zu
> 32Bit shiften kann. Die AVRs glaub ich nicht...

Der Compiler setzt das beim AVR in zwei Byte-Zugriffe um, geschoben wird 
da gar nicht.

von STK500-Besitzer (Gast)


Lesenswert?

>> int intvalue=0;
>> char *low_byte = (char*) &intvalue;
>> char *high_byte = (char*) (&intvalue)+1;

>Auch das ist nicht portabel. Je nach Prozessor kann es sein dass das
>low_byte hier gar nicht das low byte ist, sondern das high byte.

Das was Thorsten vorgeschlagen hat, macht doch eigentlich der Compiler, 
wobei dieser dann auch die richtige Zuordnung (Position der Bytes) 
trifft, oder?

von Random .. (thorstendb) Benutzerseite


Lesenswert?

shiftet denn der avr 8x in einem takt?

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Der AVR shiftet überhaupt nicht, weil der Compiler schlau genug ist 
einen 8-Bit-Shift durch einen entsprechenden Bytezugriff zu ersetzen.

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.