Forum: Compiler & IDEs int in zwei uint8_t verpacken (TWI Übertragung)


von Gast (Gast)


Lesenswert?

Hallo Forum, ich habe zwei Controller über den TWI-Bus gekoppelt (zwei 
Atmega 8 @ 16MHz)

Jetzt würde ich gerne einen 16 Bit int Wert übertragen (in diesem Fall 
einen Messwert und eine Jahreszahl).
Ich habe etwas im Forum geschaut und denke, dass man den 16 Bit Wert auf 
zwei Variablen mit je 8 Bit aufteilen muss, um ihn zu übertragen:
1
volatile unsigned int year;
2
uint8_t yearL, yearH;
3
4
yearL = year;
5
yearH = year >> 8;

Damit sollte der int in zwei uint8_t zerlegt sein, die sich so 
prinzipiell auch übertragen lassen.
Wie muss ich nun die beiden empfangenen Werte verknüpfen, um wieder 
einen int zu erhalten? Mit zwei uint8_t kann ich recht wenig anfangen, 
geschweige denn berechnen oder darstellen.

Vielen Dank & Gruß

von Ich (Gast)


Lesenswert?

volatile unsigned int year;
uint8_t yearL, yearH;

year  = yearL;
year |= yearH << 8;

MfG

von D. E. (stb)


Lesenswert?

Obiges Beispiel müsste fehlerhaft sein, da yearH << 8 null ergibt, wenn 
yearH eine 8-Bit Variable ist.

So sollte es ohne Compilerwarnungen tun:

1
volatile unsigned int year;
2
uint8_t yearL, yearH;
3
4
year = (unsigned int) yearH;
5
year <<= 8;
6
year |= (unsigned int) yearL;

STB

von Jürgen (Gast)


Lesenswert?

Hi,

diese Struktur ermöglicht einen Byte bzw Integer Zugriff auf die 
gemeinsamme Var val.

   //--------------------------------------
   union
   {
      uint val;
      struct
      {
         uchar msb;
         uchar lsb;
      }a;
   }b;
   //--------------------------------------
   b.val = xy;  // Wert in int schreiben
   x = b.a.msb; // msb lesen
   y = b.a.lsb; // lsb lesen


Gruß Jürgen

von Johannes M. (johnny-m)


Lesenswert?

D. E. wrote:
> Obiges Beispiel müsste fehlerhaft sein, da yearH << 8 null ergibt, wenn
> yearH eine 8-Bit Variable ist.
Spielt aber im Grunde genommen keine Rolle, da Berechnungen 
grundsätzlich mindestens in 16 Bit (int) durchgeführt werden 
(ANSI-konform).

Was allerdings immer gemacht werden sollte, ist eine Konversion nach 
unsigned, sonst kann es beim Schieben Probleme geben (allerdings eher 
beim Schieben nach rechts).

Generell ist eine Typkonversion jedoch ratsam. Dann weiß der Compiler 
auch, dass man das wirklich so meint, wie es da steht...

von Ich (Gast)


Lesenswert?

Hallo,

der OP fragte nach dem "Prinzip" und nicht nach lauffähigem Code.

@ D.E
@ Johannes M.
durch die Deklaration der Variablen hat der Compiler alles was er 
braucht.

@ D.E
@ Jürgen
in der Programmiersprache C liegt die Würze in der Kürze :-)

MfG

von D. E. (stb)


Lesenswert?

@Ich
Auch Du wirst lernen, daß sauberer Programmierstil unter Umständen mehr 
Zeit spart als die paar Millisekunden die Du beim Tippen sparst. <:O)


Grüße

STB

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Johannes M. wrote:
> D. E. wrote:
>> Obiges Beispiel müsste fehlerhaft sein, da yearH << 8 null ergibt, wenn
>> yearH eine 8-Bit Variable ist.
> Spielt aber im Grunde genommen keine Rolle, da Berechnungen
> grundsätzlich mindestens in 16 Bit (int) durchgeführt werden
> (ANSI-konform).

Dann ist entweder die Aussage falsch, der Compiler (gcc 4.3.2) nicht 
ANSI-konform, oder er hat nen Bug.

Aus
1
unsigned char year, yearL, yearH;
2
void foo()
3
{
4
    year  = yearL;
5
    year |= yearH << 8;
6
}

bastelt avr-gcc 4.3.2 -Os -std=c99 -ansi
1
foo:
2
  lds r24,yearL   ;  yearL, yearL   ;  8  *movqi/4  [length = 2]
3
  sts year,r24   ;  year, yearL   ;  10  *movqi/3  [length = 2]
4
  ret   ;  25  return  [length = 1]

von Gast (Gast)


Lesenswert?

1
volatile unsigned int year;
2
uint8_t yearL, yearH;
3
4
year = (unsigned int) yearH;
5
year <<= 8;
6
year |= (unsigned int) yearL;

Funktioniert perfekt! Vielen Dank dafür!
Die anderen Beispiele funktionieren alle genauso, ich habe mir über den 
UART die Ergebniss der anderen Umwandlungen mit verschiedensten Werten 
ausgeben lassen. Leider bin ich noch ziemlich am Anfang mit meinen 
Kenntnissen, deswegen kann ich da auf den ersten Blick keinen 
Unterschied erkennen, funktioniert ja alles wie es soll...

>der OP fragte nach dem "Prinzip" und nicht nach lauffähigem Code.

Och naja, den Umsatz Prinzip->Quellcode hätte ich dann auch noch 
erfragt, so fit bin ich nicht. Prinzipiell muss ich ja auch nur die 
Operation umkehren, das Prinzip habe ich schon verstanden ;-)

Vielen Dank & Grüße

von Ich (Gast)


Lesenswert?

Hallo,

@ Johann L.

> unsigned char year, yearL, yearH;
year war als unsiged int deklariert.
yearL und yearH als uint8_t

MfG

von Johannes M. (johnny-m)


Lesenswert?

Johann L. wrote:
> Dann ist entweder die Aussage falsch, der Compiler (gcc 4.3.2) nicht
> ANSI-konform, oder er hat nen Bug.
Ersteres! Klar, ist ja AVR, und bei einer 8-Bit-Plattform muss der 
Compiler sowas natürlich optimieren dürfen. Wäre ziemlich katastrophal, 
wenn tatsächlich alles in 16 Bit gerechnet würde...

EDIT:
Ich hat allerdings auch (ausnahmsweise?) recht: Das Ergebnis sollte 
schon 16 Bit haben...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Ich wrote:
> Hallo,
>
> @ Johann L.
>
>> unsigned char year, yearL, yearH;
> year war als unsiged int deklariert.

oops, der böse tipp-Teufel war am Werk

von Ich (Gast)


Lesenswert?

... habe immer recht :-)

von Johannes M. (johnny-m)


Lesenswert?

Ich wrote:
> ... habe immer recht :-)
"Ich lüge nie" sagte der notorische Lügner...;-)

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.