Forum: Mikrocontroller und Digitale Elektronik 16bit werte über I2C senden


von Peter (Gast)


Lesenswert?

Hallo,

Ich möchte einen 16bit wert über I2C senden. Meine Sendefunktion lautet 
wie folgt
1
void I2cBigWrite(int bigVal) {  
2
  Wire.write((byte *)&bigVal, sizeof(int));
3
}
Und empfangen wird es wie folgt:
1
uint8_t receivedbyte = Wire.read();
2
    RS422.print("LOW Byte: ");
3
    RS422.println(receivedbyte);
4
    // Read high byte into buffer
5
6
    receivedbyte = Wire.read() ;
7
    RS422.print("HIGH Byte: ");
8
    RS422.println(received byte);

Wenn ich jedoch bspw den Wert 1000 Sende erhalte ich folgendes:

LOW Byte: 232
HIGH Byte: 255


Wie setze ich das nun zusammen um nachher wieder den Wert 1000 zu 
bekommen?

Vielen Dank!

Grüße

Peter

von Falk B. (falk)


Lesenswert?

@ Peter (Gast)

>Wenn ich jedoch bspw den Wert 1000 Sende erhalte ich folgendes:

Wer sendet 1000?

>LOW Byte: 232
>HIGH Byte: 255

232*256 + 255 = 59647

Das kann so oder so niemals 1000 sein.

>Wie setze ich das nun zusammen um nachher wieder den Wert 1000 zu
>bekommen?

Highbyte * 256 + Lowbytes

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Peter schrieb:
> Wenn ich jedoch bspw den Wert 1000 Sende erhalte ich folgendes:
>
> LOW Byte: 232
> HIGH Byte: 255
>
> Wie setze ich das nun zusammen um nachher wieder den Wert 1000 zu
> bekommen?

 1000d = 3E8h
 E8h = 232d

 Also, LowByte ist richtig, ob und wie und was du da als HighByte
 sendest ist fraglich.
 IdleLine ergibt 255, uberprufe nochmal deine Senderoutine.

: Bearbeitet durch User
von Peter (Gast)


Lesenswert?

Okay, habe mal meine Sendefunktion überarbeitet, sie Schluckt jetzt nur 
16bit variablen:
1
void I2cBigNum(int16_t bigNum){
2
    byte myArray[2];
3
    myArray[0] = (bigNum >> 8);
4
    myArray[1] = bigNum ;
5
    Wire.write(myArray, 2);
6
}

Meine Empfängerfunktion ist diese:
1
    
2
uint8_t low = Wire.read();
3
    RS422.print("LOW Byte: ");
4
    RS422.println(low);
5
    // Read high byte into buffer
6
7
   uint8_t high= Wire.read() ;
8
    RS422.print("HIGH Byte: ");
9
    RS422.println(high);
10
11
    RS422.print("Gesamtbyte :");
12
    uint16_t voll= low;
13
    voll = voll << 8 | high;
14
    RS422.println(voll);

Das Ergebnis lautet dann jedoch 1023, anstatt 1000... Teste ich es mit 
1050 anstatt 1000 ist das Ergebnis 1279. Gibt es dazu eine Erklärung?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Peter schrieb:
> Das Ergebnis lautet dann jedoch 1023, anstatt 1000... Teste ich es mit
> 1050 anstatt 1000 ist das Ergebnis 1279. Gibt es dazu eine Erklärung?

 Ja.
 Jetzt ist dein HighByte OK, aber LowByte nicht.

 Nochmal überarbeiten ;)

 Tip:
 Wie ware es wenn du die beiden Bytes erst empfangst und danach
 ausgibst ?

: Bearbeitet durch User
von Frickelfritze (Gast)


Lesenswert?

Peter schrieb:
> Gibt es dazu eine Erklärung?

Die Arduino Help gibt folgendes Besipiel.
1
void loop()
2
{
3
  Wire.requestFrom(2, 6);    // request 6 bytes from slave device #2
4
  while(Wire.available())    // slave may send less than requested
5
  {
6
    char c = Wire.read();    // receive a byte as character
7
    Serial.print(c);         // print the character
8
  }
9
  delay(500);
10
}

Entscheidend ist wohl dass du deinem AVR erst sagen musst wieviel
du empfangen willst.

Deine jetzige Form verschluckt das zweite Byte vermutlich da
Wire.read() erst ausgerufen wird wenn das 2 Byte schon längst
gesendet wurde.

von Karl (Gast)


Lesenswert?

du schickst ein int16_t und möchtest daraus ein uint16_t zusammenbauen. 
Das geht so nicht, weil die int16_t intern als 2er-Komplement 
dargestellt werden. Entweder musst du also wieder ein int16_t als 
Ausgabe verwenden oder das ganze konvertieren.

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Wie wäre es einfach mit Mod und Div?

von Max (Gast)


Lesenswert?

Karl schrieb:
> du schickst ein int16_t und möchtest daraus ein uint16_t zusammenbauen.
> Das geht so nicht, weil die int16_t intern als 2er-Komplement
> dargestellt werden. Entweder musst du also wieder ein int16_t als
> Ausgabe verwenden oder das ganze konvertieren.

Das ist ein guter Hinweis: Wenn du in C++ auf eine `signed` Variable den 
`>>` Operator anwendest, dann wird daraus ein arithmetischer 
Rechtsshift, also mit Sign Extension.
Um sicher zu sein könntest du deine 16-bit Werte erst einmal in einen 
unsigned casten. Ein einfacher `static_cast<uint16_t>()` belässt die 
bits im Speicher unangetastet.
Dann kannst du die bits beliebig verschieben, die Daten senden, am 
anderen Ende wieder unsigned zusammenbauen und erst ganz am Schluss 
wieder zurueck casten: `static_cast<int16_t>()`.

Wuerde mich interessieren, ob das vielleicht dein Problem loest.

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.