Hallo, wende mich hier mal an mein "kleines" Problem. Vorgeschichte. Habe eine Schaltung (danke an die Hilfe der Kollegen hier) gebaut die mit einem Sensor ein Analog Signal an den Mikrocontroller gibt. Dort wird er umgewandelt und dann am Display ausgegeben. Jetzt passt alles so weit. Jetzt möchte ich gerne die Daten auch vom Mikrocontroller auf die SD-Karte schreiben lassen. Das Board ist ein: Stellaris LM3S8962 verwendete Fatlibrary: FatFs - FAT file system R0.04b Hier mein Code bis jetzt: static FRESULT fresult; static FATFS fatfs; static FIL fil; void sd_card(double value) { RIT128x96x4Disable(); if (k<160 && Benutzerdelay>0) { sprintf(&array_value[k], "%.2f\n", value); k+=8; } WORD written; if (k==160) { k=161; fresult = f_mount(0, &fatfs); fresult = f_open(&fil, "value.txt" , FA_CREATE_NEW | FA_WRITE); fresult = f_write(&fil, array_value, sizeof(array_value) ,&written); fresult = f_close(&fil); } RIT128x96x4Enable(1000000); RIT128x96x4Init(1000000); RIT128x96x4StringDraw("Werte werden geschrieben", 60, 46, 15); SysCtlDelay(5000000); } Mein Wunsch ist das das es die Daten so anzeigt. XX.XX Einheit 1. Messung XX.XX Einheit 2. Messung usw. ich kriege es damit hin das die Daten nacheinander hingeschrieben werden. 12.30 14.56 11.87 12.01 usw. jedoch krieg ich nicht eine neue Zeile hin und den Text. Habe jetzt die ganze Zeit überall was gesucht und nichts gefunden. Könnt ihr mir weiterhelfen? Habt ihr vielleicht eine Möglichkeit (die finde ich 100 Mal besser aber krieg sie nicht hin) das z.b. das Programm so abläuft. Funktion wird aufgerufen, Wert wird in ein Array geschrieben, das in ein String und dann in die Datei. Falls es nochmal aufgerufen wird soll es dort anfangen wo es aufgehört hat und einfach eine Zeile weiterschreiben. Im Moment wartet er bis das Array voll ist und schreibt das ganze Array rein. Mit dem nächsten hätte ich immer eine feste Arraygröße und es schreibt einfach im nächste block weiter auf der SD char temp_array[20]; // int i = 0; for (i;i<20;i++) {temp_array=0;} Array sieht folgendermaßen aus mit Beispiel werten 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [1][2][.][3][2][][m][s][][1][.][][M][e][s][s][u][n][g][\n] // \n für neue Zeile? sprintf(&array_value[0], "%.2f\n", value); array_value[5] = ' '; array_value[6] = 'm'; array_value[7] = 's'; array_value[8] = ' '; array_value[9] = (int) laufvariable; /hier soll immer die aktuelle zahl stehen wie mach ich da ein typecast? array_value[10] = '.'; array_value[11] = ' '; array_value[12] = 'M'; array_value[13] = 'e'; array_value[14] = 's'; array_value[15] = 's'; array_value[16] = 'u'; array_value[17] = 'n'; array_value[18] = 'g'; array_value[19] = '\n'; WORD written; fresult = f_mount(0, &fatfs); fresult = f_open(&fil, "value.txt" , FA_CREATE_NEW | FA_WRITE); fresult = f_write(&fil, array_value, sizeof(array_value) ,&written); fresult = f_close(&fil);
:
Verschoben durch Moderator
Ich denke, du schaust dir einmal alle Format-Optionen von printf/sprintf an, und spielst ein paar Tage damit. Ein gutes C-Buch wird dabei helfen.
Hi Windows will als Zeichen am Zeilenende ein carrige return + linefeed aber dein /n erzeugt wohl nur den LF es müsste gehen wenn du /r/n schreibst oder in nem ordentlichen Texteditor (ich verwende Notepad++) das end of line Symbol änderst/konvertierst. Und was das weiterschreiben in der gleichen Datei angeht kenn ich zwar die FAT Bibliothek nicht aber intuitiv würde ich sagen das du beim Datei öffnen nicht FA_CREATE_NEW verwenden darfst sondern irgendwas mit append oder so, da musst du mal in die doku schauen. Ich hoffe das hilft dir weiter. Gruß
Und wenn du schon dabei bist, das C Buch zum Thema "was kann ich mit den Formatieroptionen der printf Funktionen anstellen", dann kies auch gleich noch das Hauptkapitel ueber Strings noch mal durch. Auch da duerften so einige Grundlagen nicht verstanden worden sein. Sprich: Du hast massive Wissensdefizite. Aber nicht in der Benutzund der SD-Karten Funktionen sondern am ganzen drumherum.
Habe den Befehl sprintf nicht genau angeschaut muss ich zugeben. Habe bis jetzt nur mit c++ programmiert und dachte das wird schon. Merke aber das es doch nciht so leicht transerierbar ist da ich mit der namespace std gearbeitet habe. Ich bin jetzt so weit das auf der Karte das geschrieben wird (Text File im Anhang) Hier der Code
1 | void sd_card(wert, messung) |
2 | {
|
3 | int temp = 0; |
4 | char wert_char[31]; |
5 | for(0;temp<31;temp++) |
6 | {wert_char[temp]=0;} |
7 | |
8 | |
9 | sprintf(wert_char,"%d. Messung ---> PH-Wert = %.2f",messung,wert); |
10 | WORD written; |
11 | fresult = f_mount(0, &fatfs); |
12 | fresult = f_open(&fil, "wert.txt" , FA_CREATE_ALWAYS | FA_WRITE | FA_READ); |
13 | if(&fil) |
14 | { fresult = f_lseek(&fil,sizeof(fil));} |
15 | fresult = f_write(&fil, wert_char, sizeof(wert_char) ,&written); |
16 | fresult = f_close(&fil); |
17 | }
|
Was ist mein Fehler`?
:
Bearbeitet durch User
Da fehlt immer noch der Zeilentrenner: \n z.b. Und der buffer wert_char kann zu klein werden, wenn messung mehrstellig ist. Ausserdem brauch der Terminator \0 noch Platz. Also noch mal im K&R über Strings und Files lesen.
du willst hier
1 | fresult = f_write(&fil, wert_char, sizeof(wert_char) ,&written); |
nicht sizeof benutzen. Du willst den String, der in wert_char steht, so wie er ist aufs File geschrieben haben. sizeof liefert dir die Größe des Arrays in Bytes. Die Größe des Arrays! Aber das ist nicht notwendigerweise die Länge des Strings, der in diesem Array gespeichert ist. Diese Länge kriegst du z.b. mit strlen.
1 | sprintf( wert_char, "%d\r\n", i ); |
2 | ...
|
3 | f_write( &fil, wert_char, strlen( wert_char ), &written ); |
4 | ...
|
jetzt schreibt f_write genau den String, so wie er ist, auf das File. Nicht mehr und nicht weniger. Wenn dann am File immer noch Quatsch steht, dann hast du den String nicht richtig zusammen gebaut. Und sorg dafür, dass das Array ausreichend groß ist! Es hat keinen Sinn an dieser Stelle zu kleckern (zumindest jetzt noch nicht. Wenn das Programm mal fertig ist, sieht die Sache anders aus). Da stolpert man immer wieder drüber, dass man sich eine Formatierung zusammenbaut, die in Summe dann das Array überläuft. Da das ganze in einer FUnktion lokal zusammengefasst ist und du auf deinem µC wahrscheinlich nicht unter Speichermangel leidest, brauchst du hier nicht knausern. Definiere das Array zb 256 Zeichen gross, dann hast du erst mal ausreichend Reserven ohne dass du bei der geringsten Formatieränderung sofort in Speicherüberläufe reinläufst. Dafür kannst du dir das
1 | for(0;temp<31;temp++) |
2 | {wert_char[temp]=0;} |
dann auch sparen.
:
Bearbeitet durch User
Das hier
1 | fresult = f_lseek(&fil,sizeof(fil));} |
ist auch sicher nicht das, was du tun willst. -> Nochmal die Doku der SD_Routinen studieren. Da gibt es sicher ein Append Flag, dass du beim Open angeben kannst und welches dafür sorgt, dass hinten am bisherigen File weiter geschrieben wird.
Vielen Dank an euch drei (Karl Heinz, PittyJ und LittleHelper) Durch PittyJ habe ich mich nochmal explizit mit sprintf zusammengefasst. Ich finde es auf c++ einfacher.Wusste aber bis dato nicht das man es so in c benutzen kann. Durch LittleHelper habe ich den richtigen Modus ausgewählt (FA_OPEN_ALWAYS) und f_lseek. Habe sogar beim recherchieren noch ein paar Funktionen für mich entdeckt die ich gleich mit implementiert habe (lösch Funktion des Files). Durch KarlHeinz habe ich meine Funktion wirklich sauber implementiert. Ich hatte es zwar vorhin mit sizeof hinbekommen jedoch war es sauber implementiert für messungen bis 9999 (Speicherbereich). Mehr wäre auch nicht nötig gewesen. Aber ich fand deinen Ansatz mit strlen um längen besser da man mit der Zeit vielleicht doch mal mehr Messungen machen möchte und/oder man das Programm für eine andere Anwendung nehmen könnte. Vielen Dank euch drein nochmal :) Falls jemand Interesse haben sollte an dem Code kann er mir gerne schreiben dann schicke ich ihm den Code gerne zu.
Nijen T. schrieb: > Durch KarlHeinz habe ich meine Funktion wirklich sauber implementiert. > Ich hatte es zwar vorhin mit sizeof hinbekommen Mit Sichderheit nicht. Wie lang der String ist, der hier
1 | sprintf(wert_char,"%d. Messung ---> PH-Wert = %.2f",messung,wert); |
ensteht, kannst du doch ohne Kenntnis der Werte gar nicht wissen. Vor allen Dingen die Anzahl der Messungen nimmt bei überschreiten der 10-er, 100-er Grenze etc. um 1 Zeichen zu. Fazit: Dein String hat keine definierte, immer gleiche Länge. Damit kannst du dein Array überhaupt nicht passend dafür dimensionieren und damit ist auch ein sizeof sinnlos. sizeof ist eine statische Sache, die vom Compiler erledigt wird. Da ist nichts mit 'zur Laufzeit ermitteln'. (Ja ich weiss, mit dem letzten C Standard gibt es da eine Ausnahme. Aber um die gehts hier nicht) Damit schreibst du aber 0-Bytes ins File und bei Textfiles ist so etwas oft tödlich. Wiviele Leseroutinen von weiterverarbeitenden Programmen damit rechnen und damit klar kommen, will ich lieber nicht wissen. Die Anzahl dürfte nicht allzu hoch sein. > jedoch war es sauber > implementiert für messungen bis 9999 (Speicherbereich). Mehr wäre auch > nicht nötig gewesen. > Aber ich fand deinen Ansatz mit strlen um längen besser da man mit der > Zeit vielleicht doch mal mehr Messungen machen möchte und/oder man das > Programm für eine andere Anwendung nehmen könnte. Vor allen Dingen ist es DIE Methode mit der man Texte in ein File schreibt, wenn man schon kein fprintf hat oder eine andere Funktion die einen String in ein File schreibt, welches das von alleine regelt.
:
Bearbeitet durch User
@ Nijen T. (nijen) >Habe den Befehl sprintf nicht genau angeschaut muss ich zugeben. >Habe bis jetzt nur mit c++ programmiert und dachte das wird schon. LÄCHERLICH! Du hast nicht mal die GRUNDLAGEN von C drauf und faselst von C++? Du hast bestenfalls ein paar Arduino Beispielscripte kompiliert!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.