Forum: Mikrocontroller und Digitale Elektronik Hilfe bei Code um von Mikrocontroller auf SD zu schreiben


von Nijen T. (nijen)


Lesenswert?

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
von PittyJ (Gast)


Lesenswert?

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.

von littleHelper (Gast)


Lesenswert?

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ß

von Karl H. (kbuchegg)


Lesenswert?

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.

von Nijen T. (nijen)


Angehängte Dateien:

Lesenswert?

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
von PittyJ (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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
von Karl H. (kbuchegg)


Lesenswert?

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.

von Nijen T. (nijen)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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
von Falk B. (falk)


Lesenswert?

@ 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
Noch kein Account? Hier anmelden.