Forum: Mikrocontroller und Digitale Elektronik int to char[] to uint8_t[] to char[]


von alex (Gast)


Lesenswert?

Hallo Zusammen,

brauche eure Unterstützung um meinen Knoten im Hirn zu beseitigen.

Zur Historie:
Ich habe ein kleines Sensorboard mit einem ATMega1284p gebaut. Alle 
Sensordaten auf dem Board sind vom Typ int (weil die Temperatur negativ 
sein kann). Ich verwende die Funktion itoa, um die Daten in ein char 
array zu überführen und per BLE (UART) an meine Handy-App zu übertragen, 
was auch wunderbar funktioniert.

Jetzt möchte ich die Daten auf dem Sensorboard noch auf einer 
microSD-Karte aufzeichnen. Hierzu verwende ich die Bib von 
http://www.mikrocontroller.net/articles/AVR_FAT32, was grundlegend auch 
funktioniert. Allerdings verwenden die Bibliotheksfunktionen zum Lesen 
und Schreiben durchweg den Datentyp uint8_t.
Aus file.c:
1
uint8_t ffread(void)
2
void ffwrites( uint8_t *s )

Damit die SD-Kartenfunktionalität in mein bisheriges Programm integriert 
werden kann, brauche ich nun CODE, welcher ein char-array in uint8_t[] 
zum Schreiben und beim Lesen wieder zurück convertiert/castet, um den 
"differ in signdeness" Meldungen zu entgehen.
Mein Knoten besteht nun darin, dass ich mir nicht ganz sicher bin, ob 
ich durch das "hinundhercasten/convertieren" von Datentypen ungewollte 
Probleme bekommen kann bzw ob das nicht eleganter gelöst werden könnte.

Derzeit sieht der CODE wie folgt aus und wird auch ohne Fehlermeldungen 
compiliert (AVR Studio 4.19 Build 730):
1
  char write_buffer[16] = "";
2
  uint8_t read_buffer [16] = "";
3
  uint8_t *ptr_read_buffer = read_buffer;
4
5
  
6
  int temp = -99;          //beispielhaft ausgelesene Temperatur von Sensor
7
  itoa(temp,write_buffer,10);    //wandeln in char array und speichern in write_buffer
8
9
  // ------------------------------
10
  // das array auf 15-Zeichen füllen (für den hier nicht gegebenen Rest meines Programms erforderlich!)
11
  write_buffer[14] = write_buffer[2];
12
  write_buffer[13] = write_buffer[1];
13
  write_buffer[12] = write_buffer[0];
14
  int ii;
15
  for (ii=0;ii<12;ii++){
16
    write_buffer[ii] = '0';
17
  }
18
  write_buffer[15] = '\0';
19
20
  // -> 000000000000-99 in write_buffer
21
  // ------------------------------
22
23
  // zum Schreiben: char -> uint8_t
24
  uint8_t *convert_write_data;
25
  convert_write_data=(uint8_t*) &write_buffer;
26
27
  //schreibe Daten in Datei tempmax_file
28
  write_to_file(tempmax_file, convert_write_data);    // verwendet: void ffwrites( uint8_t *s )
29
30
  //lese geschriebene Daten (Zeichen 0 bis 14) und schreibe diese in read_buffer
31
  read_from_file(tempmax_file, 0, 14, ptr_read_buffer);  // verwendet: uint8_t ffread(void)
32
33
  // Für BLE/UART-Ausgabe: uint8_t -> char
34
  char *convert_read_data;
35
  convert_read_data = (char*) &read_buffer;
36
37
38
39
  debug_string_send("von SDCard gelesen: ");        // eigene Funktion zum Senden von Strings per UART
40
  debug_string_sendln(convert_read_data);          // Funktion wie oben nur mit LF und CR
41
42
  // Ausgabe:
43
  // von SDCard gelesen: 000000000000-99

Der Code funktioniert wie gesagt wie gewollt, allerdings hatte ich 
diesen Fall von "Typumwandlungen" bisher noch nie gebraucht, daher bin 
ich mir unsicher ob das IMMER so funktioniert wie ich mir das erhoffe.

Würde mich sehr freuen wenn mir jemand ein Feedback zukommen lassen 
könnte.


Liebe Grüße
Alex

von Peter II (Gast)


Lesenswert?

Es ist gar keine Konvertierung notwendig. Du machst auch keine, das ist 
eine einfacher Typcast.

so geht es etwas einfacher.
1
write_to_file(tempmax_file, (uint8_t*)&write_buffer );

Die Frage ist, warum man es als Klartext (string) in die Datei schreibt. 
Man könnte auch die int-werte direkt in die Datei schreiben, dann spart 
man sich die ganze Stringumwaldlung.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Peter II schrieb:
> Die Frage ist, warum man es als Klartext (string) in die Datei schreibt.

Damit man die Datei mit einem simplen Texteditor lesen kann?

von Peter II (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Damit man die Datei mit einem simplen Texteditor lesen kann?

wenn man das denn braucht. Ich die meisten Dateien auf meinen PC schauen 
ich nur mit dem dazugehörigen Programm rein.

von Dirk B. (dirkb2)


Lesenswert?

Peter II schrieb:
> write_to_file(tempmax_file, (uint8_t*)&write_buffer );

Da ist das & zuviel.

Peter II schrieb:
> wenn man das denn braucht. Ich die meisten Dateien auf meinen PC schauen
> ich nur mit dem dazugehörigen Programm rein.

Ich nicht.

von Peter II (Gast)


Lesenswert?

Dirk B. schrieb:
> Peter II schrieb:
>> write_to_file(tempmax_file, (uint8_t*)&write_buffer );
>
> Da ist das & zuviel.

eigneltich nicht. write_buffer ist ein Array und kein Pointer. (es geht 
beides).

Merkwürdig finde ich mehr, das write_to_file keine länge mit übergeben 
bekommt.

von chris (Gast)


Lesenswert?

Peter II schrieb:
> eigneltich nicht.

Eigentlich doch!

Entweder

(uint8_t*)&write_buffer[0]

oder

(uint8_t*)write_buffer

von Peter II (Gast)


Lesenswert?

chris schrieb:
> Peter II schrieb:
>> eigneltich nicht.
>
> Eigentlich doch!

g++ akzeptiert beides ohne Warnungen.

von casud (Gast)


Lesenswert?

> g++ akzeptiert beides ohne Warnungen.

Ja klar, da danach ein Typecast folgt. Falsch ist es trotzdem.

von Peter II (Gast)


Lesenswert?

casud schrieb:
> Falsch ist es trotzdem.

wie kommst du darauf das es falsch sein muss?

Es ist beides zulässig.

von Alex (Gast)


Lesenswert?

Danke für die Antworten, ich werde das gleich mal testen!
Ich habe später auf der SD-Karte neben den Werten auch Text, weshalb ich 
das schlichtweg plump über den Texteditor lesen möchte. Daher alles in 
Strings.

Die Funktion write_to_file bekommt keine Länge (des Strings, wenn das 
gemeint war?), da die darin enthaltene Bibliotheks-Funktion ffwrite so 
lange Zeichen schreibt bis diese auf das '\0'-Zeichen stößt.

Da auf meine Bedenken mit den Typcasts keine Einwände kamen gehe ich mal 
davon aus, dass dieses Vorgehen der gängige Weg ist, den ihr auch 
einschlagen würdet? Wie gesagt, hab das bisher noch nicht gebraucht...


Alex

von Peter II (Gast)


Lesenswert?

Alex schrieb:
> Die Funktion write_to_file bekommt keine Länge (des Strings, wenn das
> gemeint war?), da die darin enthaltene Bibliotheks-Funktion ffwrite so
> lange Zeichen schreibt bis diese auf das '\0'-Zeichen stößt.

ist halt etwas merkwürdig. dann könnte man mit der Funktion keine binary 
Daten schreiben. Da hätte ich erwartet das sie ein char* als Parameter 
hat. Dann würde klar sein, das sie bis zum \0 alles rausschreibt.

von Kaj (Gast)


Lesenswert?

Peter II schrieb:
> wie kommst du darauf das es falsch sein muss?
>
> Es ist beides zulässig.
Weil es verschiedene Dinge sind.
1
&write_buffer
ist die Adresse des Pointers der auf write_buffer zeigt. Dieser liegt 
nun zufaellig an genau der selben adresse wie der Start des Arrays.
1
write_buffer
und
1
&write_buffer[0]
sind hingegen die Adressen des ersten Elemntes von write_buffer.
Das sind verschiedene Sachen. &write_buffer funktioniert, ist aber 
trotzdem falsch, weil es was gaenzlich anderes ist.

Mit folgendem Code wird das Problem deutlicher:
1
#include <stdio.h>
2
3
int main(void)
4
{
5
    int arr[10];
6
    int *p_arr = arr;
7
    
8
    printf("&arr     : %p\n", &arr);
9
    printf("arr      : %p\n", arr);
10
    printf("&arr[0]  : %p\n\n", &arr[0]);
11
    printf("&p_arr   : %p\n", &p_arr);
12
    printf("p_arr    : %p\n", p_arr);
13
    printf("&p_arr[0]: %p\n", &p_arr[0]);
14
    
15
    return 0;
16
}
1
&arr     : 0x74af68afe0f0
2
arr      : 0x74af68afe0f0
3
&arr[0]  : 0x74af68afe0f0
4
5
&p_arr   : 0x74af68afe0e8
6
p_arr    : 0x74af68afe0f0
7
&p_arr[0]: 0x74af68afe0f0

von Peter II (Gast)


Lesenswert?

Kaj schrieb:
> Mit folgendem Code wird das Problem deutlicher:

was soll daran deutlicher werden? Klar das das & bei einem Pointer nicht 
mehr so funktioniert. Das habe ich bereits geschrieben. Es ging aber um 
eine Array und da funktioniert ist.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Peter II schrieb:
> Es ging aber um eine Array und da funktioniert ist.

Aber darum muss man nicht auf so einem kryptischen Mist beharrlich 
bestehen - auch wenn es ausnahmsweise bei einem Array stimmt.

Besser man merkt sich den allgemeinen Fall

   var != &var

und fertig.

Es gibt keinen Grund, ausgerechnet bei Arrays - nur weil es da zufällig 
passt - davon abzuweichen.

Oder nenne bitte einen trifftigen Grund. Ich kenne keinen.

: Bearbeitet durch Moderator
von Peter II (Gast)


Lesenswert?

Frank M. schrieb:
> Es gibt keinen Grund, ausgerechnet bei Arrays - nur weil es da zufällig
> passt - davon abzuweichen.

ich sehe es genau andersrum, warum sollte bei Array vom dem Schema 
abweichen?

int i;
addr = &i;

int ii[12];
addr = &ii;

beides sind variablen und keine Zeiger.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Peter II schrieb:
> ich sehe es genau andersrum

Das ist Ansichtssache.

Stell Dir folgendes vor:

int ii[2][3][4];

Und jetzt beantworte folgende Fragen:

1. Von welchem Typ ist ii[0][0][0]?
2. Von welchem Typ ist ii[0][0]?
3. Von welchem Typ ist ii[0]?
4. Von welchem Typ ist ii?
5. Wofür brauche ich dann noch &ii?

: Bearbeitet durch Moderator
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.