int in zwei uint8_t verpacken (TWI Übertragung)

Gast #1060485
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ß
#1060536
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
Gast #1060543
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
#1060689
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...
Gast #1060935
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
Persönliche Seite #1061294
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]
Gast #1061416
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
#1061753
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...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren