Forum: Compiler & IDEs Datentyp Formatierung


von Gäst_5 (Gast)


Lesenswert?

Hallo,

ich habe folgendes Problem:

Ich sende vom ATmega:

c = 55;
fwrite(&c, sizeof(uint16_t), 1, f);

an einen RaspberryPi und lese dort mit:

char    rx_header_buffer [4] = {0};
read(uart0_filestream, rx_header_buffer, 2);


Nach einem

printf("%i ... %i \n", rx_header_buffer[3],...,rx_header_buffer[0])

erscheint folgendes auf der Konsole:

0 0 0 55

D.h. die 55 wurde richtig übertragen und befindet sich nun in einem 
Array aus 4 Char Typen, also in 32 Bit.

Nun möchte ich mit dieser Zahl ganz normal weiter arbeiten:

z.B. so:
if (rx_header_buffer == 55){ printf("Ja");}

oder so:
printf("Data Size: %s \n", rx_header_buffer);


Leider funktioniert das nicht so wie ich mir das denke.

Was muss ich tun?

von Peter II (Gast)


Lesenswert?

Gäst_5 schrieb:
> Was muss ich tun?

wenn du ein int sendest, solltest du auch ein int lesen und kein char*

außerdem musst du beachten das ein int auf dem atmel 2byte ist und auf 
den Raspi 4byte. Dazu kommt noch eventuell ein Big/Little Endian 
problem.

von Gäst_5 (Gast)


Lesenswert?

> wenn du ein int sendest, solltest du auch ein int lesen und kein char*

Woher weiß denn der Pi das ich einen Int gesendet habe? Die Daten kommen 
doch über den UART und werden Bit für Bit übertragen.
Die obige read Funktion liest 2 Byte und schreibt sie in 
rx_header_buffer.

Wenn ich nun folgendes probiere:

int    rx_header_buffer;
read(uart0_filestream, rx_header_buffer, 2)

Kommt folgender Fehler:
invalid conversion from 'int' to 'void*' [-fpermissive]

> außerdem musst du beachten das ein int auf dem atmel 2byte ist und auf
> den Raspi 4byte.

Das ist richtig.
Mit:
fwrite(&c, sizeof(uint16_t), 1, f);
sende ich 2 Byte vom ATmega zum Pi.

Mir ist auch noch nicht so richtig klar, wie ich das Zahlen bzw. Werte 
senden am besten mache.
- dachte als Zeichen dauert zu lang, weil ich ja dann für z.B. 55 16-Bit 
brauch.

>Dazu kommt noch eventuell ein Big/Little Endian problem.

Noch nie gehört.. ich google mal.

von Peter II (Gast)


Lesenswert?

Gäst_5 schrieb:
> Woher weiß denn der Pi das ich einen Int gesendet habe?

gar nicht aber du kannst es einfach als int lesen so wie du es einfach 
als int sendest.

senden:
fwrite(&c, sizeof(uint16_t), 1, f);

lesen:
fread(&c, sizeof(uint16_t), 1, f);

von Gäst_5 (Gast)


Lesenswert?

> fread(&c, sizeof(uint16_t), 1, f);

Geht leider nicht, da fread eine Highlevel Funktion ist und ein File 
benötigt.

Für den Pi verwende ich aber:
uart0_filestream = open(UART, O_RDWR | O_NOCTTY);

Ich habe somit kein FILE sondern einen Int-Wert.

von Peter II (Gast)


Lesenswert?

Gäst_5 schrieb:
>> fread(&c, sizeof(uint16_t), 1, f);
>
> Geht leider nicht, da fread eine Highlevel Funktion ist und ein File
> benötigt.
>
> Für den Pi verwende ich aber:
> uart0_filestream = open(UART, O_RDWR | O_NOCTTY);
>
> Ich habe somit kein FILE sondern einen Int-Wert.

dann verwende read. Das geht doch dort genauso.

von Gäst_5 (Gast)


Lesenswert?

> dann verwende read. Das geht doch dort genauso.

genau das mache ich auch und da wären wir wieder bei meiner 
ursprünglichen Frage angelangt ;-)

von Peter II (Gast)


Lesenswert?

Gäst_5 schrieb:
> genau das mache ich auch und da wären wir wieder bei meiner
> ursprünglichen Frage angelangt ;-)

habe ich doch, wenn lies doch einfach in ein int ein und nich in ein 
char.

von Karl H. (kbuchegg)


Lesenswert?

Gäst_5 schrieb:
>> dann verwende read. Das geht doch dort genauso.
>
> genau das mache ich auch und da wären wir wieder bei meiner
> ursprünglichen Frage angelangt ;-)

Und die Antwort ist immer noch die gleiche.
Der Empfänger kann nicht a priori wissen, wieviele Bytes kommen werden 
und welcher Datentyp da dahinter steckt.
Es sei denn, es gibt eine Absprache zwischen Sender und Empfänger. Diese 
Absprache muss der Programmierer in Code umsetzen. Wie auch immer diese 
Absprache auch aussieht. Und bei rein binärer Datenübertragung landet 
man dann oft bei dem Problem, dass der Empfänger eine Möglichkeit 
braucht, wie er reine Nutzdaten von Steuerdaten unterscheiden kann. Denn 
den Bytes sieht man nicht an, was sie sind.

von Gäst_5 (Gast)


Lesenswert?

wenn ich dies ändere:

int     rx_header_buffer;
read(uart0_filestream, &rx_header_buffer, sizeof(int));

stützt das Programm ab...

von Εrnst B. (ernst)


Lesenswert?

Übertrag deine Werte als Ascii:
+ Leicht les- und debugbar
+ Plattformunabhängig
+ Mit jedem terminal-Programm empfangbar (Screen, minicom, Putty, ...)
- mehr Bytes zu übertragen
- itoa-Methode am AVR benötigt

Oder zumindest in Netzwerk-Byteorder (htons, ntohs)

von Karl H. (kbuchegg)


Lesenswert?

Gäst_5 schrieb:
> wenn ich dies ändere:
>
> int     rx_header_buffer;
> read(uart0_filestream, &rx_header_buffer, sizeof(int));
>
> stützt das Programm ab...

Ist ein int auf deinem Pi 2 Bytes groß?


Genau aus dem Grund sind die später eingeführten Datentypen wie

int16_t   oder
uint16_t

so nützlich. Das steht drauf, wieviele Bits es sind (und damit wieviele 
Bytes)

von Gäst_5 (Gast)


Lesenswert?

> Ist ein int auf deinem Pi 2 Bytes groß?

nein, 4.

Aber wo liegt das Problem, dass es gleich abstürzt?
Wenn die Int Datei vom ATmega 2 Byte ist, sollte der PI diese doch 
trotzdem in die ersten 2 Byte des 4-Byte Int Typs des Pi schaffen, oder?

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Ist ein int auf deinem Pi 2 Bytes groß?

um das näher auszuführen:
ein int ist NICHT auf allen Computern gleich groß!

Der Datentyp int ist gedacht als die "Leib und Magenspeise" einer CPU. 
Das womit sie am leichtesten zurecht kommt, und man trotzdem noch 
einigermassen vernünftig rechnen kann.
Auf einem AVR ist ein int 2 Bytes (also 16 Bit) groß. Auf einer 32-Bit 
CPU ist ein int aber meistens 4 Bytes groß (also 32 Bit). Wo sollen denn 
auf der UART Übertragung plötzlich 2 zusätzliche Bytes herkommen, wenn 
der Sender nur 2 Bytes wegschickt, der Empfänger aber auf 4 Bytes 
wartet?

von Karl H. (kbuchegg)


Lesenswert?

Εrnst B✶ schrieb:
> Übertrag deine Werte als Ascii:

das ist für einen Anfänger sowieso das Beste, bis er die ganzen Untiefen 
von Byteorder, Protokoll und Timeout durchschaut hat.

von Gäst_5 (Gast)


Lesenswert?

Mal ein zwischenzeitliches Danke für die Hilfe! :-)

> Wo sollen denn
> auf der UART Übertragung plötzlich 2 zusätzliche Bytes herkommen, wenn
> der Sender nur 2 Bytes wegschickt, der Empfänger aber auf 4 Bytes
> wartet?

Okay, ich dachte dann ist der Rest einfach irgendwelcher Mist der dem 
Filestream entnommen wird.

Ich habe nun folgendes geändert und schick dem Pi 32 Bit:

fwrite(&c, sizeof(uint32_t), 1, f);

...unverändert stürzt es ab.

von Karl H. (kbuchegg)


Lesenswert?

> - dachte als Zeichen dauert zu lang, weil ich ja dann für
> z.B. 55 16-Bit brauch.

Und? Wieso ist das ein Problem?

(In Wirklichkeit sind für "55" 3 Bytes zu übertragen, weil du ja auch 
noch eine Endekennung brauchst, an der der Empfänger erkennen kann, dass 
jetzt nichts mehr kommt und die Zahl in Textform vollständig vorliegt. 
Aber auch dann ist das noch kein Problem, es sei denn man will ein Video 
von einem Rechner zum anderen Streamen oder muss 4 Gigabyte übertragen. 
Um die Aussentemperatur von A nach B zu schicken, spielt das aber sowas 
von überhaupt keine Rolle)

von Gäst_5 (Gast)


Lesenswert?

>> Übertrag deine Werte als Ascii:

Das Projekt soll aber darauf hinauslaufen, dass ich viele Messwerte 
schnell vom ATmega an den Pi übertragen will.

Habt ihr dafür Ratschläge, wie ich das am besten anstelle?
Ich habe auch noch nirgends rausgefunden, wie groß dieser UART RX-FIFO 
Speicher im Pi ist.
Was passiert denn wenn ich dem Pi über den UART 1000 Zeichen schicke, 
und sie 30 sek. später erst von dem FIFO Speicher nehme?
Wie viele Byte kann der maximal Fassen?

von Peter II (Gast)


Lesenswert?

Gäst_5 schrieb:
> Was passiert denn wenn ich dem Pi über den UART 1000 Zeichen schicke,
> und sie 30 sek. später erst von dem FIFO Speicher nehme?
> Wie viele Byte kann der maximal Fassen?

warum solltest du das machen. so ein RaSpi ist doch so schnell das man 
ein paar tausend mal pro sekunden abfragen kann. Mach dir darüber 
erstmal keine sorgen. (Du solltest das abfragen in einem eigenen thread 
machen damit er nicht ausgebremst wird und dann die daten selber 
puffern)

von Gäst_5 (Gast)


Lesenswert?

> (Du solltest das abfragen in einem eigenen thread
> machen damit er nicht ausgebremst wird und dann die daten selber
> puffern)

Ich hab mir dazu folgendes überlegt:

Der Pi sendet dem ATmega ein Zeichen oder String und fordert ihn damit 
auf, die Anzahl der anstehenden Messwerte, quasi als Header des 
Datenstromes, und sofort anschließend die Messwerte zu übertragen.

Mit der read Funktion im Pi kann ich festlegen wie viel vom Filestream 
gelesen wird um dann mit Hilfe der Anzahl, die ich anfangs als Header 
übertragen habe, die kompletten Daten individuell lesen zu können.

Anschließend will ich die Daten dann in einem File auf der SD Karte des 
Pi ablegen.

Könnte das so klappen?

von Peter II (Gast)


Lesenswert?

Gäst_5 schrieb:
> Könnte das so klappen?

ja, sehe dabei kein Problem. Du musst nur auch damit rechnet das Zeichen 
verloren gehen (und wenn nur jemand dem atmel resettet). Also musst ein 
sinnvolles Timeout einbauen. Und wenn du 100% sicher gehen willst das 
alles richtig übertragen ist. Dann solltest du nach den Messwerten noch 
eine Prüfsumme übertragen.

von Gäst_5 (Gast)


Lesenswert?

> ja, sehe dabei kein Problem

Und wie sollte ich diese ganze Messwerte übertragen?
Dachte als Zeichen wird es insgesamt zu viel und damit dann zu langsam.

Somit wollte ich die einzelnen Messwerte als Int übertragen.

Und damit stehen ich wieder vor dem Problem, was ich immer noch nicht in 
den Griff bekommen habe.

Wenn in dem RX FIFO-Speicher des Pi nur 16 Bit liegen, ich mit

read(uart0_filestream, &rx_header_buffer, sizeof(int));

aber 32 Bit einlesen möchte, meint Karl Heinz Buchegger das dies zum 
Absturzt führt.
Nun sende ich aber 32 Bit, können ja auch mehr sein, mit:

fwrite(&c, sizeof(uint32_t), 1, f);

Trotzdem stürzt das Programm ab.

Woran liegt das?

von Peter II (Gast)


Lesenswert?

Gäst_5 schrieb:
> fwrite(&c, sizeof(uint32_t), 1, f);
> Trotzdem stürzt das Programm ab.

dann zeige uns ein vollständiges Programm, das wir sehen was du machst.

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.