Hallo zusammen,
ich sende Daten vom PC zum Controller RN-Mega 2560 und die gleichen
Daten wieder zurück. Wenn ich den ersten Datensatz "127X1" mit WriteFile
sende erhalte ich den korrekten Datensatz "127X1" wieder per ReadFile
zurück. Beim zweiten Datensatz sende ich "127Y1" und erhalte
"127X1ÌÌÌÌ“ŠupLñ*" anstatt "127Y1" zurück. Nach dem Senden sende ich
noch "\r\n" per ReadFile, um das Ende des Datensatzes mitzuteilen.
Mein Bascom-Programm sieht folgendermaßen aus:
1
$prog , 255 , &B11011100 , '&B11011001 , 'Quarz an / Teiler aus / Jtag aus
N hat den wert 8. weil ich 8 bytes übertrage. Oder muß n den genauen
Wert des zu übertragenen Characters haben? Bin gerade unterwegs und
kanns nicht testen.
Auweia.
Da muß drinstehen, wieviel Bytes aus dem angegebenen Buffer übertragen
werden sollen! Und im nächsten Parameter bekommst Du zurück, wieviel
tatsächlich übertragen wurden. Die beiden Werte müssen nicht
notwendigerweise gleich sein.
Aber noch Schlimmer, in Deinem "Buffer" sind nur 3 Bytes ("\r\n")!
Wenn Du dem WriteFile sagst es soll 8 Bytes senden, sendest Du jede
Menge Mist.
Du solltest dir ganz schnell eine
WriteString
Funktion machen, die dir genau diese Details (Anzahl Bytes ist gleich
der Stringlänge) abnimmt.
Solch kleine Hilfsfunktionen, die sich um 1 oder mehrere Details für
einen bestimmten Datentypen kümmern, sind das wie man sich selber das
Leben einfacher machen kann.
Du solltest zumindest dwBytesRead befragen, wieviele Zeichen empfangen
wurden und nicht einfach annehmen, nur weil der ReadFile Call
zurückkommt, hättest du 6 Zeichen gekriegt. ReadFile weiß nicht, auf
wieviele Zeichen du wartest und kann auch vor Erreichen deiner magischen
6 Zeichen Grenze schon w.o. geben.
wenn du also weißt, dass du eine bestimmte Zeichenanzahl abwarten musst,
dann gehört das in eine Schleife, in der du die dwBytesRead aufsummierst
und solange schleifst, bis du deine Anzahl beisammen hast.
Und das du hier
string_parameter_read = read_buffer;
(string_parameter_read ist wohl eine String Klasse mit einem überladenen
Zuweisungsoperator) sicherheitshalber den C-String auch noch sauber
terminieren solltest, sollte eigentlich eine Selbstverständlichkeit
sein. (*)
read_buffer[ sizeof( read_buffer ) - 1 ] = '\0';
string_parameter_read = read_buffer;
(*) ... die ich dir aber als C++ verwöhnter Programmierer nachsehe.
C-Strings sind um einiges komplizierter zu benutzen als String-Klassen.
Du musst wesentlich sorgfältiger damit umgehen und selbst dann sind sie
immern noch wesentlich fehleranfälliger. Das rundum-sorglos Paket einer
Klasse, die auf sich selbst aufpasst, existiert dort nicht.
Thomas Holländer schrieb:> Wie frage ich denn dwBytesRead ab?
Das ist eine Variable.
Die hat einen Wert
1
....ReadFile(hSerial,&read........
2
3
if(dwBytesRead==5)
4
MessageBox(..."Hurra, ich hab 5 Bytes bekommen"...);
5
elseif(dwBytesRead==4)
6
MessageBox(..."Schmoll, ich hab bis jetzt nur 4 Bytes gekriegt"...);
Oder eben in deinem Fall eine while Schleife aufziehen, die solange
nicht verlassen wird, bis deine erwarteten 5 Bytes beisammen sind. Kein
Mensch garantiert dir, dass du die Bytes in einem Stück bei einem
einzigen Aufruf von ReadFile bekommst.
> So?> int laenge_read_buffer = sizeof (dwBytesRead);
Duko lesen! In dwBytesRead informiert dich Windows darüber, wieviele
Bytes es in deinen Buffer geschrieben hat. Dein Buffer kann 2 Kilobyte
gross sein. Das heisst aber noch lange nicht, dass da dann auch 2
Kilobytes reingeschrieben werden, wenn nur 5 Bytes daherkommen und der
ReadFile wegen einem Timeout abgebrochen wird. Dann sagt dir eben
dwbytesRead nach dem Aufruf, dass 5 Bytes in den Buffer geschrieben
wurden.
msgboxIDss=MessageBox(NULL,(LPCWSTR)L"Fehler bei WriteFile!",
7
(LPCWSTR)L"Fehler",MB_OK|MB_ICONEXCLAMATION);
8
EndDialog(hwnd,1);
9
returnTB_ERROR;
10
}
11
elseif(laenge_write_r!=dwBytesWrite)
12
{
13
string_fehlerfrei_gesendet="Nein";
14
}
15
else
16
{
17
string_fehlerfrei_gesendet="Ja";
18
}
Beim ersten WriteFile und beim ReadFile analog
Thomas Holländer schrieb:> Erster Durchlauf:> write_char hat den Wert 127X1> laenge_write_char hat den Wert 6
Was soll der Mist? Warum willst Du bei 5 Zeichen 6 Bytes senden?
> laenge_write_r hat den Wert 1
Das passt dann wieder.
Beim Lesen fehlt irgenwo noch das Stringendezeiche, mach nach dem
ReadFile ein:
1
read_buffer[dwBytesRead]='\0';
Das ist vermutlich die Ursache für den ausgegebenen Müll.
Ein weiteres Problem ist, daß Du mehr Zeichen sendest als Du liest.
Beim ersten Lesen bekommst Du "127X1", beim zweiten "\r127X", beim
dritten "1\r127" usw.
Thomas Holländer schrieb:> Versteh ich nich.>> Ich habe jetzt die Längen 4 bis 8 durchprobiert. Beim zweiten Senden> stimmt der Wert nicht mehr und die Doku sagt mir auch nichts.
Du gehen mit Korb in Lager und sagen zu Chef:
Ich brauchen Schrauben M8. Da seien Korb, der fassen maximal 200
Schrauben.
Chef verschwinden hinter Regale und holen Schrauben.
Wenn Cheffe wiederkommen, er geben dir Korb und sagen: Hab dir 10
Schrauben reingegeben, mehr hab ich nicht.
Was gibt es da nicht zu verstehen?
Und wenn du 200 Schrauben brauchst, dann musst du halt wieder zum Chef
gehen und dir die nächste Ladung holen. Dann kriegst du vielleicht 15
(und damit hast du in Summe 25). Und beinm nächsten mal (eine halbe
Stunde später) hat Cheffe wieder 23 neue Schrauben im Regal und gibt sie
dir. Dann hast du in Summe 48. Und so geht das dahin, bis du deine 200
Schrauben beisammen hast.
... schrieb:> Thomas Holländer schrieb:>> Erster Durchlauf:>> write_char hat den Wert 127X1>> laenge_write_char hat den Wert 6> Was soll der Mist? Warum willst Du bei 5 Zeichen 6 Bytes senden?
Die Länge ermittle ich durch:
1
laenge_write_char = sizeof(write_char);
Siehe ganz oben. Warum der Wert 6 anstatt 5 ermittelt wird weis ich
nicht. Werd ich gleich mal auf 5 ändern.
... schrieb:> Beim Lesen fehlt irgenwo noch das Stringendezeiche, mach nach dem> ReadFile ein: read_buffer[dwBytesRead] = '\0';> Das ist vermutlich die Ursache für den ausgegebenen Müll.
Wo und wie baue ich das denn mit dem Endezeichen ein?
Thomas Holländer schrieb:> ... schrieb:>> Thomas Holländer schrieb:>>> Erster Durchlauf:>>> write_char hat den Wert 127X1>>> laenge_write_char hat den Wert 6>> Was soll der Mist? Warum willst Du bei 5 Zeichen 6 Bytes senden?>> Die Länge ermittle ich durch:>>
1
> laenge_write_char = sizeof(write_char);
2
>
>> Siehe ganz oben. Warum der Wert 6 anstatt 5 ermittelt wird weis ich> nicht. Werd ich gleich mal auf 5 ändern.>> ... schrieb:>> Beim Lesen fehlt irgenwo noch das Stringendezeiche, mach nach dem>> ReadFile ein: read_buffer[dwBytesRead] = '\0';>> Das ist vermutlich die Ursache für den ausgegebenen Müll.>> Wo und wie baue ich das denn mit dem Endezeichen ein?
Spätestens jetzt sollte klar sein:
Du brauchst ganz dringend Literatur. Wenn dein C++ Buch keinen Abschnitt
über C-Strings hat, dann musst du eine kleine C++ Pause einlegen und dir
mit einem C-Buch die Grundlagen der C-Programmierung beibringen. So hat
das wenig Sinn.
Thomas Holländer schrieb:> Die Länge ermittle ich durch:> laenge_write_char = sizeof(write_char);>> Siehe ganz oben. Warum der Wert 6 anstatt 5 ermittelt wird weis ich> nicht. Werd ich gleich mal auf 5 ändern.
Autsch, das tut ja schon weh.
Du solltest Dir definitiv ein gutes Buch zu C und C++ zulegen und
nachschauen was der sizeof Operator macht! Das was Du da erwartest macht
er jedenfalls nicht. C-Strings sind anscheinend bisher ein Buch mit
sieben Siegeln für Dich. Da hilft nur lesen, lesen und nochmals lesen!!!
Ein String in C mit 5 Zeichen benötigt 6 Bytes Speicherplatz, weil das
Ende der Zeichenkette irgendwie gekennzeichnet werden muß. Und in C
macht man das, indem man ein 0 (Null, '\0') Byte hinten dran hängt.
Desweiteren hast Du anscheinend das Ganze als Unicode Projekt angelegt.
Dafür sollte man aber auf jeden Fall auch wissen, was Unicode ist, was
der Unterschied zwischen ASCII und Unicode ist, welche verschiedenen
Kodierungen es gibt und wie das Ganze in C/C++ realisiert ist und wie
man diese Sachen ineinander umwandelt.
Hier mal ein Stück Code zum drüber nachdenken. Solange Du aber nicht
verstehst was da wann, wie und warum passiert, brauchst Du gar nicht
erst weitermachen.
Habe den Quelltext aus dem vorherigen Beitrag übernommen. Die Daten
kommen jetzt. Vielen Dank.
Allerdings, verzögert. Wenn ich die Daten zum Controller sende kommen
sie erst nach ein paar Sekunden zurück. Beim debuggen erhalte ich die
Daten sofort, liegt wahrscheinlich an der Verzögerung, die der
Haltepunkt auslöst.
Wer kann mir sagen, warum die verzögert kommen?
Vielen Dank.
Grüße
datatom