Forum: Mikrocontroller und Digitale Elektronik UART strings einlesen


von Tim S. (tim_s31)


Lesenswert?

Hallo zusammen, bin kurz vorm verzweifeln.

Ich möchte über UART große Datenmengen empfangen. Die Daten bestehen zum 
Teil aus ASCII Text, aus Hex Werten in als Text, und Gleitkommawerte in 
Textform. z.B.: "FF\rFF\rTestdaten\r-0.121\r". Ich habe auch schon \0 
als trennzeichen versucht oder ';'. Ohne erfolg.
Habe bereits viele der Lösungsvarienten hier aus der Forum getestet, 
jedoch ohne Erfolg.

Meine Routine sieht folgendermaßen aus:
1
unsigned char USARTReadChar(){
2
  while(!(UCSR0A&(1<<RXC0))){        //Wait until reception is complete.
3
  }
4
  return UDR0;                //Return the byte read.
5
}
6
7
void WriteEEPROM() //Wird von der Mainloop aufgerufen
8
{
9
char data[500];  //auch schon versucht als pointer char * data zu deklarieren
10
while((USARTReadChar()) != '\r')
11
{
12
        data[i++] = USARTReadChar();
13
  //*data++ = USARTReadChar();  //Funktioniert ebenfalls nicht
14
}
15
USARTWriteS(data);
16
17
}
Wenn ich nun über Terminal eben einen string wie oben beschrieben 
übermittle erhalte ich entweder keine Antwort, nur 1 Zeichen oder wie in 
diesem Codebeispiel etwas kyptisches wie "mAmA?" Auch wenn ich die Werte 
ändere oder mehr oder weniger Zeichen übermittle kommt dies als Antwort 
zurück.

Vielen Dank im Vorraus =)

Gruß Tim

: Bearbeitet durch User
von jo (Gast)


Lesenswert?

>Hallo zusammen, bin kurz vorm verzweifeln.

Es ist wohl Zeit damit loszulegen.

Ohne kompletten Code wird dir hier keiner helfen können bzw. wollen.

Gruß Jonas

von Purzel H. (hacky)


Lesenswert?

Die einfachste Loesung ist die Laenge des Strings zuerst zu uebertragen. 
zB als 16 oder 32 bit integer, erst die Laenge, dann die Daten. Dann 
kann der empfaeger runterzaehlen.

von Karl H. (kbuchegg)


Lesenswert?

Tim S. schrieb:
> Hallo zusammen, bin kurz vorm verzweifeln.

Dann geh erst mal einen Schritt zurück und überprüfe, ob die 
Übermittlung von Charactern überhaupt fehlerfrei funktioniert. Das ist 
der Grundbaustein, auf dem alles aufbaut und es gibt viele 
Fehlermöglichkeiten. Angefangen von einer falschen Baudrate, einer 
falschen Taktrate des µC bis hin zu einem falsch ausgekreuzten seriellem 
Kabel.

Nicht immer gleich mit den komplizierteren Dingen, wie der Übertragung 
einer ganzen Zeile (bestehend aus einzelnen Zeichen) anfangen. Erst mal 
die Basisding, wie eben die Übertragung der einzelnen Zeichen prüfen!



> while((USARTReadChar()) != '\r')
> {
>         data[i++] = USARTReadChar();
>   //*data++ = USARTReadChar();  //Funktioniert ebenfalls nicht
> }

nichts und niemand hindert dich daran, das Zeichen, welches von 
USARTReadChar empfangen wird, gleich mal wieder auszugeben.
1
void WriteEEPROM() //Wird von der Mainloop aufgerufen
2
{
3
  unsigned char c;
4
  char data[500];
5
6
  USARTWriteS( "WriteEEPROM " );
7
  c = USARTReadChar();
8
  USARTWriteChar( c );
9
10
  while( c != '\r')
11
  {
12
    data[i++] = c;
13
14
    c = USARTReadChar();
15
    USARTWriteChar( c );
16
  }
17
18
  USARTWriteS( "Zeile: '" );
19
  USARTWriteS(data);
20
  USARTWriteS( "'\n" );
21
}

> ändere oder mehr oder weniger Zeichen übermittle kommt dies als Antwort
> zurück.

Jetzt gibt dir der Code jedes Zeichen gleich wieder aus und zwar so, wie 
der µC es empfangen hat.
Die Ausgabe des Textes "WriteEEPROM " am Anfang der Funktion hat den 
Sinn, sicherzustellen, dass die Übertragung grundsätzlich funktioniert 
(eh scho wissen: Baudrate und so). Siehst du in deinem Terminal den Text 
so nicht, dann brauchst du dich erst mal um die Zeile überhaupt nicht 
kümmern, denn dann funktioniert die USART nicht richtig und du musst das 
erst mal korrigieren. Siehst du den Text, dann weißt du schon mal, dass 
der Teil grundsätzlich funktioniert. Da dir jedes Zeichen von der USART 
gleich nach Erhalt zurückgeschickt wird, so dass du es in deinem 
Terminal siehst, kannst du auch sehen, was der µC eigentlich verstanden 
hat. Und zwar Zeichen für Zeichen. Wenn das nicht korrekt ist (was 
eigentlich nach dem Vortest nicht mejr sein sollte, aber man weiß ja 
nie), dann hast du auch wieder einen Anhaltspunkt, wo du suchen musst. 
Sind die Zeichen korrekt aber der String im Endeffekt nicht, dann wissen 
wir ebenfalls wie die Fehlersuche weitergeht.

Langere Rede kurzer Sinn: Du hast eine UART. Wenn du nicht weißt was im 
µC vor sich geht, dann benutze die UART, so dass dir der µC erzählt was 
er tut und dir so bei der Fehlersuche hilft.

von Karl H. (kbuchegg)


Lesenswert?

Allerdings ist mir bei Schreiben der letzten Antwort ein Fehler 
aufgefallen
1
...
2
while((USARTReadChar()) != '\r')
3
{
4
        data[i++] = USARTReadChar();
5
  //*data++ = USARTReadChar();  //Funktioniert ebenfalls nicht
6
}
7
...

es wird wohl kaum sinnvoll sein, in einem Schleifendurchlauf 2 mal 
USARTReadChar aufzurufen und so jedes 2.te Zeichen entweder beim 
Speichern oder beim Abfragen der Schleifen-Endbedingung zu ignorieren.
Das erklärt allerdings nicht die 'seltsamen Zeichen', die du in der 
Antwort siehst.

von Tim S. (tim_s31)


Angehängte Dateien:

Lesenswert?

Entschuldige ich wollte nicht einen riesen Batzen Code auf einmal hier 
rein werfen. Habe nun mein *.c File angehängt.
Die Methode soll nachdem ein Datensatz eingengangen ist diesen in einem 
char array data speichern, anschließend werte ich das array mit einer 
switchcase aus. Mein problem jedoch ist, das der datensatz nicht richtig 
empfangen wird. Also wenn ich einen string empfange und über uart zur 
bestätigung wieder zurück gebe dieser nicht dem ausgangsstring 
entspricht. daher vermute ich, dass dieser nicht richtig im array 
abgelegt wird.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:
> Allerdings ist mir bei Schreiben der letzten Antwort ein Fehler
> aufgefallen

ein zweiter Fehler besteht darin, dass du den empfangenen "String" nicht 
korrekt terminierst. Solange da das nicht tust hast du eben keinen 
'String' sondern erst mal nur eine Abfolge von Bytes.

von Christopher B. (chrimbo) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
>   c = USARTReadChar();

Was vermutlich auch gleich sein Problem löst, weil er in seinem Code 
jedes zweite Zeichen weggeschmissen hat.

Tim S. schrieb:

> while((USARTReadChar()) != '\r') // <- Das Zeichen wird nicht gespeichert!
> {
>         data[i++] = USARTReadChar();
>   //*data++ = USARTReadChar();  //Funktioniert ebenfalls nicht
> }
> USARTWriteS(data);
>
> }

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:
> Karl Heinz schrieb:
>> Allerdings ist mir bei Schreiben der letzten Antwort ein Fehler
>> aufgefallen
>
> ein zweiter Fehler besteht darin, dass du den empfangenen "String" nicht
> korrekt terminierst. Solange da das nicht tust hast du eben keinen
> 'String' sondern erst mal nur eine Abfolge von Bytes.#

Wo ist eigentlich die Variable i in deinem Code beheimatet?
Bis jetzt (hab das Zip File noch nicht studiert) sehe ich in der 
Funktion nichts, was garantieren würde, dass i am Beginn der Funktion 
den Wert 0 hat.

Ich sehe allerdings auch nicht, warum die Variable i in der Funktion 
nicht eine lokale Variable sein könnte. Was im übrigen höchst sinnvoll 
wäre.
1
void WriteEEPROM() //Wird von der Mainloop aufgerufen
2
{
3
  unsigned char i = 0;
4
  unsigned char c;
5
  char data[500];
6
7
  USARTWriteS( "WriteEEPROM " );
8
  c = USARTReadChar();
9
  USARTWriteChar( c );
10
11
  while( c != '\r')
12
  {
13
    data[i++] = c;
14
15
    c = USARTReadChar();
16
    USARTWriteChar( c );
17
  }
18
  data[i] = '\0';
19
20
  USARTWriteS( "Zeile: '" );
21
  USARTWriteS(data);
22
  USARTWriteS( "'\n" );
23
}

: Bearbeitet durch User
von Tim S. (tim_s31)


Lesenswert?

@Karl Heinz schrieb:

> Jetzt gibt dir der Code jedes Zeichen gleich wieder aus und zwar so, wie
> der µC es empfangen hat.
> Die Ausgabe des Textes "WriteEEPROM " am Anfang der Funktion hat den
> Sinn, sicherzustellen, dass die Übertragung grundsätzlich funktioniert
> (eh scho wissen: Baudrate und so). Siehst du in deinem Terminal den Text
> so nicht, dann brauchst du dich erst mal um die Zeile überhaupt nicht
> kümmern, denn dann funktioniert die USART nicht richtig und du musst das
> erst mal korrigieren. Siehst du den Text, dann weißt du schon mal, dass
> der Teil grundsätzlich funktioniert. Da dir jedes Zeichen von der USART
> gleich nach Erhalt zurückgeschickt wird, so dass du es in deinem
> Terminal siehst, kannst du auch sehen, was der µC eigentlich verstanden
> hat. Und zwar Zeichen für Zeichen. Wenn das nicht korrekt ist (was
> eigentlich nach dem Vortest nicht mejr sein sollte, aber man weiß ja
> nie), dann hast du auch wieder einen Anhaltspunkt, wo du suchen musst.
> Sind die Zeichen korrekt aber der String im Endeffekt nicht, dann wissen
> wir ebenfalls wie die Fehlersuche weitergeht.
>
> Langere Rede kurzer Sinn: Du hast eine UART. Wenn du nicht weißt was im
> µC vor sich geht, dann benutze die UART, so dass dir der µC erzählt was
> er tut und dir so bei der Fehlersuche hilft.

Also prizipiell scheint die uart verbindung richtig konfiguriert zu 
sein.
wenn ich im Terminal folgedes sende: "01;F1;01;test;"
erhalte ich folgende ausgabe: "01<\r>Zeile: 'g: '<\n>g: ?"
die ersten beiden Zeichen scheinen also richtig übermittelt worden zu 
sein und dann geht etwas schief =(


auf deine Frage hin, i ist ein unsigend int und wird oben  zu beginn der 
methode definiert und deklariert.

: Bearbeitet durch User
von Heinz S. (Gast)


Lesenswert?

Tim S. schrieb:
> Entschuldige ich wollte nicht einen riesen Batzen Code auf einmal hier
> rein werfen. Habe nun mein *.c File angehängt.

Das sollst du auch nicht. Du sollst ein minimales, aber lauffaehiges 
Beispiel posten, das dein Problem zeigt. Den wilden Mischmasch von UART 
und EEPROM-Code will wirklich Niemand sehen und debuggen - auch du 
nicht.

von Karl H. (kbuchegg)


Lesenswert?

Tim S. schrieb:


> die ersten beiden Zeichen scheinen also richtig übermittelt worden zu
> sein und dann geht etwas schief =(


Jep.
Dein i hat hier
1
....
2
  for(i = 0; i <= 500; i++)
3
  {
4
    i2c_writebyte(i,EEPROM_ID,EEPROM_ADDR, *hexStringToBytes(clear));
5
  }
6
7
  char data[500];
8
  while((USARTReadChar()) != '\r')
9
  {
10
    
11
    data[i++] = USARTReadChar();
12
    
13
  }
nach der ersten for-Schleife den Wert 501. Es sollte aber den Wert 0 
haben, wenn du von Beginn an in das Array schreiben willst.

Und das ist jetzt der vierte offensichtliche Fehler.


Alles in allem sehe ich in dem Code einen Haufen Zeilen, die offenbar 
viel zu viel für dich sind, als das du es noch überblicken könntest. Da 
sind noch ein paar andere Fehler enthalten. Warum schreibst du denn 
derartige Code-Monster, wenn du ihnen noch nicht gewachsen bist? Das 
Geheimnis in der Programmierung besteht nicht darin, riesige Funktionen 
zu schreiben, sondern sich die Arbeit so in Einzelteile zu zerlegen, 
dass man jedes Einzelteil noch beherrschen kann.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> Und das ist jetzt der vierte offensichtliche Fehler.

Der fünfte offensichtliche Fehler besteht darin, dass der in der 
Funktion hexStringToBytes mittels malloc allokierte Speicher nie 
freigegeben wird.

Mit anderen Worten: Dein Programm hat ein Speicherleck.

von Tim S. (tim_s31)


Lesenswert?

Nun ich mache das im zuge eines Praktikums und versuche die projekte die 
mir gegeben werden zu bearbeiten. Ich sitze nun schon seit mehreren 
wochen an diesem ding und hangel mich eben so durch. Aber an dieser 
sache mit dem empfangen hänge ich nun schon sei 2 tagen deswegen 
probierte ich bei euch mein glück.

Jedenfalls das i = 0; zurückzusetzen hat schonmal die cyptische ausgabe 
verbessert, jedoch werden nur die ersten 2 zeichen ausgegeben.
"01<\r>Zeile: '01'<\n>01<1>"

von Karl H. (kbuchegg)


Lesenswert?

Tim S. schrieb:
> Aber an dieser
> sache mit dem empfangen hänge ich nun schon sei 2 tagen deswegen
> probierte ich bei euch mein glück.

Du hängst nicht 'an der Sache mit dem Empfangen', du hängst an 
grundlegenden Nicht-Programmieren-Können Sachen.
Immer diese Over-Statements.
Das wäre so, wie wenn ich sagen würde, ich hänge daran, nicht den Mt. 
Everest besteigen zu können, wenn ich in Wirklichkeit schon beim 
Fussmarsch über die Treppe in den 5. Stock schon ins Schnaufen komme. 
Der Mt. Everest ist nicht das eigentliche Problem ....

: Bearbeitet durch User
von Tim S. (tim_s31)


Lesenswert?

Habe nie gesagt das ich den Könner bin. Jedoch versuche ich dennoch 
meine Aufgabe zu erledigen.

Zum Speicherleck der hexStringToBytes. Mir ist bekannt dass ich den 
speicher der durch malloc allokiert wurde wieder freigeben sollte, 
jedoch kann ich außerhalb dieser methode den speicher für die retval 
variable nicht freigeben und innerhalb wird diese ja bis zum return 
verwendet.

von Karl H. (kbuchegg)


Lesenswert?

Tim S. schrieb:
> Habe nie gesagt das ich den Könner bin. Jedoch versuche ich dennoch
> meine Aufgabe zu erledigen.
>
> Zum Speicherleck der hexStringToBytes. Mir ist bekannt dass ich den
> speicher der durch malloc allokiert wurde wieder freigeben sollte,
> jedoch kann ich außerhalb dieser methode den speicher für die retval
> variable nicht freigeben und innerhalb wird diese ja bis zum return
> verwendet.

Und?
Was ist deine Schlussfolgerung daraus?

Nein einfach ignorieren ist keine Lösung.

Der springende Punkt ist, dass der ganze Ansatz so wie er gemacht wurde 
Unsinn ist. Viel zu umständlich.

von Tim S. (tim_s31)


Lesenswert?

Karl Heinz schrieb:

>
> Und?
> Was ist deine Schlussfolgerung daraus?
>
> Nein einfach ignorieren ist keine Lösung.
>
> Der springende Punkt ist, dass der ganze Ansatz so wie er gemacht wurde
> Unsinn ist. Viel zu umständlich.

Natürlich ist es sau umständlich jeden Substring eineln in einer 
switchcase zu behandeln. Da ich aber die daten nicht direkt so erhalte 
wie sie vom Format her in den EEPROM abgelegt werden müssen ist mir 
nicht besseres eingefallen. Das ist ja aber nicht das Thema. Ich wollte 
lediglich wissen wie ich einen Empfangenen string mit einzelnen Werten 
darin in ein char array ablege.

von Route_66 H. (route_66)


Lesenswert?

Tim S. schrieb:
> Ich wollte
> lediglich wissen wie ich einen Empfangenen string mit einzelnen Werten
> darin in ein char array ablege.

Hast Du denn den Fehler, den kbuchegg um 15:08 und chrimbo um 15:11 
angemahnt haben, schon beseitigt?

von Karl H. (kbuchegg)


Lesenswert?

Tim S. schrieb:

> Das ist ja aber nicht das Thema.

Da bin ich mir gar nicht mal so sicher.
Wieviel SRAM hat denn dein unbekannter µC?

Denn in der Schleife
1
...
2
  for(i = 0; i <= 500; i++)
3
  {
4
    i2c_writebyte(i,EEPROM_ID,EEPROM_ADDR, *hexStringToBytes(clear));
5
  }
6
...

hast du schon 501 Bytes deines wertvollen SRAM Speichers belegt und 
verloren. Wenn dein µC in der Größenordnung 512 Bytes komplettes SRAM 
hat, dann ist es damit sehr wahrscheinlich, dass du dir mit einem der 
nächsten Aufrufe von hexStringToBytes den Stack zerschiesst.
Spätestens aber nach dem n-ten Aufruf dieser kompletten 
Empfangs-Funktion ist allerdings bei den typischen Speichergrößen eines 
AVR Schluss mit lustig. Dann zerschiesst du dir recht sicher den Stack. 
Und das bei eigentlich bereits recht kleinem n.

> Ich wollte
> lediglich wissen wie ich einen Empfangenen string mit einzelnen Werten
> darin in ein char array ablege.

Die Frage ist ja schon beantwortet. Das Problem ist, dass es in deinem 
Code nicht nur ein Problem gibt sondern gleich mehrere. Und wenn man 
ehrlich ist, dann ist die ganze Ablegerei der empfangenen Bytes als 
String schon der erste Programm-Strategie Fehler. Ich sehe in dem Code 
bzw. in der Art und Weise wie die Auswertung aufgebaut ist nichts, was 
dies unbedingt erzwingen würde. Wenn da eine Fehlerabfrage drinnen wäre, 
die einen kompletten Datensatz als Ganzes verwerfen würde, würde es 
unter Umständen anders aussehen. Aber auch dann ist es einfacher, die 
Zahlen ganz einfach 'on the fly' zusammen zu bauen während die Bytes 
reinkommen, anstatt erst mal umständlich alles in einem String zu 
sammeln und erst hinterher auszuwerten.

> Natürlich ist es sau umständlich jeden Substring eineln in einer switchcase zu 
behandeln.

Davon rede ich nicht. Um einen derartige Fallunterscheidung kommst du 
nicht rum.
Ich rede von der Funktion in ihrer Gesamtheit. Vergleichbar mit der 
Fahrt von München nach Berlin. Es ist ziemlich unerheblich, ob du dabei 
in Paris auf der Ringautobahn fährst oder quer durch. Die ganze Fahrt 
von München über Paris nach Berlin ist es, die in Frage gestellt werden 
sollt, wenn das Ziel München-Berlin lautet. Also nicht auf einzelnen 
Details rumreiten, wenn global gesehen der ganze Ansatz schon 
zweifelhaft ist.

: Bearbeitet durch User
von Purzel H. (hacky)


Lesenswert?

dynamischen Speicher zu verwenden ist in 99% der Faelle falsch. Braucht 
man nicht.

von Tim S. (tim_s31)


Lesenswert?

Route 66 schrieb:
> Tim S. schrieb:
>> Ich wollte
>> lediglich wissen wie ich einen Empfangenen string mit einzelnen Werten
>> darin in ein char array ablege.
>
> Hast Du denn den Fehler, den kbuchegg um 15:08 und chrimbo um 15:11
> angemahnt haben, schon beseitigt?

Ja das habe ich. die laufvariable i wird nun 0 gesetzt vor der while 
schleife, das zweite Zeichen wird nicht mehr verworfen mit der while 
schleifen variante von Karl Heinz. Es werden jedoch nur die ersten zwei 
Zeichen welche ich übermittle zurückgegeben. Bsp "01234\r" zurückgegeben 
wird jedoch nur "01". Die Schleife wird also nur 2 mal durchlaufen, als 
wären die übrigen Zeichen nicht im Uart Buffer. Das '\r' wird jedoch 
erkannt. Wenn ich im Terminal kein CR beim senden mit schicke, kann ich 
beliebig viele Zeichen senden, diese werden auch zurückgegeben, jedoch 
komme ich selbst durch nachträgliches senden eines '\r' nicht mehr aus 
der Schleife

von Karl H. (kbuchegg)


Lesenswert?

Siebzehn Zu Fuenfzehn schrieb:
> dynamischen Speicher zu verwenden ist in 99% der Faelle falsch. Braucht
> man nicht.

Vor allen Dingen wenn, so wie hier, dann vom Ergebnis sowieso nur 1 Byte 
benutzt wird.

von Karl H. (kbuchegg)


Lesenswert?

Tim S. schrieb:
> Route 66 schrieb:

> Zeichen welche ich übermittle zurückgegeben. Bsp "01234\r" zurückgegeben
> wird jedoch nur "01". Die Schleife wird also nur 2 mal durchlaufen, als
> wären die übrigen Zeichen nicht im Uart Buffer. Das '\r' wird jedoch
> erkannt. Wenn ich im Terminal kein CR beim senden mit schicke, kann ich
> beliebig viele Zeichen senden, diese werden auch zurückgegeben, jedoch
> komme ich selbst durch nachträgliches senden eines '\r' nicht mehr aus
> der Schleife

Ersetz doch mal diese unsägliche hexStringtoByte Funktion durch etwas 
Vernünftiges.
Du brauchst eine Funktion, die aus einem Hex-String, von dem du weißt 
das nur 1 Byte enthalten ist, von der du also weißt, dess es nur 2 
Nibble gibt, den entsprechenden numerischen Bytewert. Dazu braucht man 
nichts dynamisch allokieren. So eine Funktion ist in 2 Minuten 
geschrieben. Sogar von dir.

Damit bist du schon mal das Problem los, dass du Speicher leakst. Mit 
allen Problemen, die dadurch entstehen können.

von Tim S. (tim_s31)


Lesenswert?

Karl Heinz schrieb:

> hast du schon 501 Bytes deines wertvollen SRAM Speichers belegt und
> verloren. Wenn dein µC in der Größenordnung 512 Bytes komplettes SRAM
> hat, dann ist es damit sehr wahrscheinlich, dass du dir mit einem der
> nächsten Aufrufe von hexStringToBytes den Stack zerschiesst.
> Spätestens aber nach dem n-ten Aufruf dieser kompletten
> Empfangs-Funktion ist allerdings bei den typischen Speichergrößen eines
> AVR Schluss mit lustig. Dann zerschiesst du dir recht sicher den Stack.
> Und das bei eigentlich bereits recht kleinem n.

> Die Frage ist ja schon beantwortet. Das Problem ist, dass es in deinem
> Code nicht nur ein Problem gibt sondern gleich mehrere. Und wenn man
> ehrlich ist, dann ist die ganze Ablegerei der empfangenen Bytes als
> String schon der erste Programm-Strategie Fehler. Ich sehe in dem Code
> bzw. in der Art und Weise wie die Auswertung aufgebaut ist nichts, was
> dies unbedingt erzwingen würde. Wenn da eine Fehlerabfrage drinnen wäre,
> die einen kompletten Datensatz als Ganzes verwerfen würde, würde es
> unter Umständen anders aussehen. Aber auch dann ist es einfacher, die
> Zahlen ganz einfach 'on the fly' zusammen zu bauen während die Bytes
> reinkommen, anstatt erst mal umständlich alles in einem String zu
> sammeln und erst hinterher auszuwerten.

Der Controler ist ein AVR Atmega168 mit 16k Speicher.

Ich gebe dir in allem was du sagst vollkommen recht, jedoch weiß ich 
nicht wie ich das ganze on the fly machen soll. Zum einen kann der 
Datensatz der ankommt unterschiedlich groß sein. Da ist es eine Lösung 
wie schon erwähnt die Länge des Datensatzes vorher zu übermitteln. Das 
kann ich auch realisieren. Jedoch die Behandlung der einzelnen 
Substrings mit unterschiedlicher Länge, welche zt noch in Hex, bool, und 
float gewandelt werden müssen stellen für mich ein problem dar für on 
the fly behandlung. Habe keine Ahnung nach welchem Schema ich da 
verfahren könnte.

Mir ist klar das es bei meiner Programmiererei an allen Ecken hapert, 
danke euch jedoch für eure Mühe und Hilfe.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> Damit bist du schon mal das Problem los, dass du Speicher leakst. Mit
> allen Problemen, die dadurch entstehen können.

Und ich möchte hinzufügen: die sauschwer zu detektieren und zu finden 
sind. Du willst Speicher nur dann dynamisch allokieren, wenn es keine 
andere Möglichkeit gibt. Ansonsten bevorzugst du IMMER statische 
Allokierung.
Diese jetzige Funktion ist darauf ausgelegt, mit beliebig vielen Bytes 
klar zu kommen. Brauchst du in deinem Code diese Flexibilität? Nein, die 
brauchst du nicht. Würde es was bringen, diese Flexibilität aufzugeben? 
Ja, das will ich meinen, das das was bringt.
Schlussfolgerung: weg damit und mit etwas ersetzt, dass für die konkrete 
Aufgabenstellung angemessen ist.

von Karl H. (kbuchegg)


Lesenswert?

Tim S. schrieb:

> Ich gebe dir in allem was du sagst vollkommen recht, jedoch weiß ich
> nicht wie ich das ganze on the fly machen soll.

Ich werfe dir einzelne Ziffern zu und du sollst die daraus resultierende 
Zahl benennen.

Ich gebe dir eine '5'.

   Du merkst dir: Aha. Die Zahl könnte 5 sein

Dann gebe ich dir eine '2'

   Du denkst dir. Gut. Die Zahl könnte also 52 sein

Ich gebe dir eine '8'.

   Du: So ein Schlingel. Also ist die Zahl 528

Ich sage: das wars, die Zahl ist fertig.

   Du: Ha, Die Zahl war 528!


Wie hast du das gemacht?
Mit jeder Ziffer, die ich dir genannt habe, ist die Zahl größer 
geworden. Wie ist sie größer geworden. Um beispielsweise aus den 52 die 
528 zu machen, hast du die 52 mit 10 multipliziert und so eine neue 
'Einerstelle' in 520 erzeugt. Dann hast du die '8' noch in ihren 
numerischen Wert 8 verwandelt und zu den 520 addiert. So bist du von 52 
auf 528 gekommen.

Der springende Punkt. An keiner Stelle hast du dir die Ziffern merken 
müssen, die ich dir zugeworfen habe. Du hast einfach jede Ziffer dazu 
benutzt, die Zahl (mit der du bei 0 begonnen hast) um jeweils die 
nächste Ziffer zu erweitern.

Das ist schon sehr weit unten.
Man kann so weit gehen, muss aber nicht unbedingt. Deine Übertragung ist 
dadurch gekennzeichnet, dass es eine textuelle Einheit gibt, von der du 
weisst, dass sie mit entweder einem ',' oder einem '\r' abgeschlossen 
wird. Du brauchst also gar nicht darauf warten, bis die Zeile 
vollständig ist. Wenn du einen ',' in den Zeichen siehst, die 
reinkommen, weißt du bereits, dass du eine textuelle Einheit vorliegen 
hast, die du Auswerten und ins EEPROM schreiben kannst. Der Vorteil: Du 
brauchst kein so großes Array um die komplette Zeile darin speichern zu 
können. Ein kleines, welches deine größte vorkommende 'textuelle 
Einheit' speichern kann (und noch ein bischen Reserve dazu) reicht 
völlig aus.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> Man kann so weit gehen, muss aber nicht unbedingt. Deine Übertragung ist
> dadurch gekennzeichnet, dass es eine textuelle Einheit gibt, von der du
> weisst, dass sie mit entweder einem ',' oder einem '\r' abgeschlossen
> wird. Du brauchst also gar nicht darauf warten, bis die Zeile
> vollständig ist. Wenn du einen ',' in den Zeichen siehst, die
> reinkommen,

Äh. Moment mal. Stimmt ja gar nicht
1
      if(term == 1)
2
      d = strtok(data,'\0');
3
      else
4
      d = strtok(NULL,'\0');

was soll den das sein?
Du benutzt strtok um in einem String nach '\0' zu suchen?

Bei aller Liebe, aber das ist so ziemlich der größte Unsinn, den ich in 
30 Jahren C und C++ Programmiererei gesehen habe. Und ich hab schon viel 
gesehen.
Die ganze Auswerterei ist, wenn man sich das mal genauer ansieht, recht 
sinnfrei.

von Tim S. (tim_s31)


Lesenswert?

Ich mach für heut erstmal feierabend und werde morgen das Programm 
weiter bearbeiten. Ist wohl Zeit das bisherige über den Haufen zu werfen 
und bei 0 zu beginnen. Vielen Dank für die Anregungen ich versuche das 
morgen in die Tat umzusetzen und melde mich dann nochmal.

Schönen Feierabend zusammen

von Tim S. (tim_s31)


Lesenswert?

Karl Heinz schrieb:

> Äh. Moment mal. Stimmt ja gar nicht
>
>
1
>       if(term == 1)
2
>       d = strtok(data,'\0');
3
>       else
4
>       d = strtok(NULL,'\0');
5
>
>
> was soll den das sein?
> Du benutzt strtok um in einem String nach '\0' zu suchen?
>
> Bei aller Liebe, aber das ist so ziemlich der größte Unsinn, den ich in
> 30 Jahren C und C++ Programmiererei gesehen habe. Und ich hab schon viel
> gesehen.
> Die ganze Auswerterei ist, wenn man sich das mal genauer ansieht, recht
> sinnfrei.

Das Stammt noch aus dem ersten Ansatz. Bin ja bisher noch nicht weiter 
gewesen als die Zeichen erstmal einzulesen. Ursprünglich war \0 der 
Delimiter für einen Substring des Datensatzes, dass das quark ist ist 
mir auch klar geworden weil viele Mehtoden diesen Nullterminierer 
verwenden und ich somit nie an die Strings gelange die im Array nach dem 
ersten \0 stehn. streich das aus deinem gedächtnis

von Route_66 H. (route_66)


Lesenswert?

Tim S. schrieb:
> Der Controler ist ein AVR Atmega168 mit 16k Speicher.

Aber nur 1k RAM.

von Joachim B. (jar)


Lesenswert?

Route 66 schrieb:
> Tim S. schrieb:
>> Der Controler ist ein AVR Atmega168 mit 16k Speicher.
>
> Aber nur 1k RAM.

eben und mit

Tim S. schrieb:
> char data[500];

wird die Luft sowas von dünne !

ein Wunder das das Programm soweit gekommen ist

im Studio4 werde ich ja immer über den Ramverbrauch informiert, im 
Arduino muss ich immer forschen wieviel Ram ich verbraucht habe

vor allen bei den Kleinen

ich bin halt verwöhnt von dem atmega1284p -> – 16K Bytes Internal SRAM

von jo (Gast)


Lesenswert?

>> Der Controler ist ein AVR Atmega168 mit 16k Speicher.

> Aber nur 1k RAM.

Ich zweifel das im der Unterschied bewusst ist.

Also warum gehst du nicht nach einer Standart-Vorgehensweise vor?
Schreib dir Diagramme. Vom Anwendungsfalldiagramm bis zum Ablaufplan 
brauchst du alles, glaub mir. Und beim nächsten und übernächsten Projekt 
auch. Und irgendwann mal kannst du Code ins Blaue schreiben. Aber das 
dauert noch, glaube uns einfach.

Gruß Jonas

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.