mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Serial.print() eines uint8_t gibt 4 Bytes aus?!


Autor: L. N. (derneumann)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe folgende Structs:
#define RF69_MAX_DATA_LEN 61

struct nodePacketTH {
  uint8_t command;
  uint8_t serialNumber[6];
  float temperature;
  float humidity;
};

struct RF69dataPacket {
  uint8_t len;
  uint8_t senderID;
  uint8_t targetID;
  uint8_t rssi;
  char buffer[RF69_MAX_DATA_LEN];
  bool ackRequested;
};

RF69dataPacket packet;
nodePacketTH nodePacket;

und folgenden Code:
for (uint8_t n = 0; n < 15; n++)
{
  Serial.print(n);
  Serial.print(": ");
  Serial.println(packet.buffer[n], HEX);
}

Die Ausgabe sieht so aus:
0: 54
1: 30
2: FFFFFFBC
3: 77
4: 14
5: 73
6: FFFFFF90
7: FFFFFFB0
8: FFFFFFB6
9: FFFFFFDB
10: 41
11: 10
12: FFFFFFF9
13: FFFFFFA7
14: 41


µC ist ein Atmega328p, Arduino Framework wird genutzt.
Wie ist denn das möglich, dass bei der Ausgabe eines Bytes plötzlich 4 
Bytes ausgegeben werden? Der Inhalt des Buffers passt, ich übertrage 
genau 15 Byte dieses Buffers auf eine andere Node (per Funk) und dort 
kommen die Daten ohne den führenden drei FF Bytes an.

Bug in der Serial.print? Hat das möglicherweise etwas mit dem Alignment 
der Struct aufgrund der floats darin zu tun?

Braucht ihr mehr Infos, oder ist der Fehler schon offensichtlich?

Danke!


edit:
for (uint8_t n = 0; n < 15; n++)
{
  snprintf(printbuf, sizeof(printbuf), "%u: %x", n, packet.buffer[n]);
  Serial.println(printbuf);
}

Gibt übrigens folgendes aus:
0: 54
1: 30
2: ffbc
3: 77
4: 14
5: 73
6: ff90
7: ff84
8: 24
9: ffdc
10: 41
11: 10
12: ffff
13: ffa6
14: 41

also nur mehr ein führendes Byte. wtf?

: Verschoben durch Moderator
Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wie ist packet definiert??
Hast du schon in der Doku von serial.printf nachgesehen?

Autor: L. N. (derneumann)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Walter schrieb:
> wie ist packet definiert??

sorry, hab ich grad ergänzt, steht jetzt oben.

Walter schrieb:
> Hast du schon in der Doku von serial.printf nachgesehen?

Naja, die Arduino Doku zu Serial.print ist sehr spärlich. Arduino halt.
Wenn ich einen int16 oder int ausgeben würde, würde ich es ja verstehen, 
aber char? char ist doch 1 byte groß.

Das hier hab ich gefunden:
https://electronics.stackexchange.com/questions/49662/arduino-why-does-serial-printlnint-hex-display-4-bytes

wirft aber nur noch mehr Rätsel auf, da ich ja eben einen char 
verwende...

Autor: A. S. (achs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
char ist (vielleicht) signed und nicht uint8_t.

: Bearbeitet durch User
Autor: A. S. (achs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. S. schrieb:
> char ist (vielleicht) signed und nicht uint8_t.

Die "langen" Zahlen sind negative Zahlen -1..-127 als unsigned 
dargestellt.

Autor: L. N. (derneumann)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. S. schrieb:
> char ist (vielleicht) signed und nicht uint8_t.

hmm, wenn ich packet so definiere:
struct RF69dataPacket {
  uint8_t len;
  uint8_t senderID;
  uint8_t targetID;
  uint8_t rssi;
  uint8_t buffer[RF69_MAX_DATA_LEN];
  bool ackRequested;
};

RF69dataPacket packet;

dann bekomme ich keine führenden Bytes bei der Ausgabe (passt also), 
dafür natürlich Compilerwarnungen bei
snprintf(packet.buffer, 8, "P%s", settingsObj.serialNumber);

á la:
invalid conversion from 'uint8_t* {aka unsigned char*}' to 'char*' 
[-fpermissive]

Autor: L. N. (derneumann)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich mir die Print.cpp anschaue, dann ist das wohl nur eine 
Anzeigesache (was ja auch durch die Tatsache bestätigt wird, dass die 
Daten richtig ankommen):

https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/Print.cpp

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Ja, die Ausgabe negativer Zahlen (char ist beim GCC defaultmäßig 
vorzeichenbehaftet) in einer von 10 verschiedenen Basis erfolgt immer im 
32-Bit-Zweierkomplement, bei 8-Bit-Werten in hex also in der Form 
FFFFFFxx. Um das zu vermeiden, musst den Wert in ein unsigned char oder 
uint8_t casten:

Serial.println((uint8_t)packet.buffer[n], HEX);

: Bearbeitet durch Moderator
Autor: L. N. (derneumann)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Yalu X. schrieb:
> Ja, die Ausgabe negativer Zahlen (char ist beim GCC defaultmäßig
> vorzeichenbehaftet) in einer von 10 verschiedenen Basis erfolgt immer im
> 32-Bit-Zweierkomplement, bei 8-Bit-Werten in hex also in der Form
> FFFFFFxx. Um das zu vermeiden, musst den Wert in ein unsigned char oder
> uint8_t casten:
>
> Serial.println((uint8_t)packet.buffer[n], HEX);

Vielen Dank. Du hast in sinnvolle Worte gefasst, was ich mir im Groben 
schon gedacht habe, nach den letzten Posts.

Wenn hier Threads geschlossen werden können, gäbe es kaum einen 
passenderen Zeitpunkt als jetzt. Frage beantwortet :-)

Autor: A. S. (achs)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Wenn Du mit printf in den Buffer schreiben möchtest, dann lass ihn char.

Wenn Du einzelne Bytes anzeigen möchtest, dann caste sie auf uint_8.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.