Hi
bin jetzt seit 4 Tagen an diesem Problem und komm nicht mehr weiter :(
Hab nen DSP mit dem ich über die Serielle Schnittstelle kommunizieren
will.
Und zwar über Folgen von zweistelligen Hex Zahlen. Also z.B. fordere ich
ihn mit "0x02 0x01 0x7F 0x80 0x03" auf, zu pingen und er antwortet das
gleiche zurück. Die Antwort kann aber bei anderen Befehlen auch
unterschiedlich lang sein.
Jetzt will ich das ganze mit nem C-Programm unter Linux machen. Wie kann
ich das empfangen, was ankommt?
anbei mal mein Programm-Code so far. Hab in allen Tutorials dies im Netz
so gibt geguckt aber es funzt einfach nicht. Teilweise aus dem Serial
Programming Howto kopiert. oben die openport funktion, weiter unten die
auslesen.
Das Öffnen des Ports funzt. Das Senden funzt auch. Aber Lesen geht
nicht. Der Port läuft im non-canonical mode. canonical geht nicht, da
wartet er ewig auf ein cr. oder read failed weil timeout.
der read Befehl gibt auch kein -1 zurück, also er liest was, aber mal
sind es o bytes und mal 5, und stimmen tun sie auch nicht. mit printf
wird nur schwachsinn angezeigt und im debugger steht 0x80 als -128 drin
und 0x03 gar nicht.
Nehme an, das ist ein Problem im Array angekommen, vielleicht falscher
datentyp, vielleicht ist VMIN oder VTIME falsch gesetzt. Vielleicht ist
auch noch was im Puffer was stört. :(
Was mach ich falsch?
Danke für eure Hilfe
LG
du must einfach mehrfach lesen. Es kann auch sein das jedes byte einzeln
ankommt. Die Frage ist wieviel du lesen musst, aber das sollte in der
Doku vom Protokoll erkennt bar sein.
was soll das flush nach dem Read?
Danke für die schnelle Antwort
stimmt, das flush brauch ich nicht, da in der openport funktion schon
der puffer vor dem lesen geleert wird ??
Gut, ich werds dann mal mit ner lese Schleife versuchen. Ist aber
komisch, dass mal alle 5 Bytes ankommen wie gewollt und mal gar keine.
Der Debugger zeigts an
VT0815 schrieb:> Gut, ich werds dann mal mit ner lese Schleife versuchen. Ist aber> komisch, dass mal alle 5 Bytes ankommen wie gewollt und mal gar keine.> Der Debugger zeigts an
weil du im debugger langsam bist, damit kann es sein das in puffer schon
5 byte das sein.
VT0815 schrieb:> Ok, ein usleep(200000) vor Aufruf der Auslesen Funktion hat es gebracht,> jetzt sind immer Daten da :)> Vielen Dank :)
das ist doch aber murks. Man sollte kein sleep verwenden!. Normalerweise
sollte read blockieren wenn man lesen will. Dann kann man einfach
byteweise einlesen. Denn ich konnte nicht sehen das du nicht-blockierend
arbeitest.
VT0815 schrieb:> Ok, ein usleep(200000) vor Aufruf der Auslesen Funktion hat es> gebracht,> jetzt sind immer Daten da :)> Vielen Dank :)
Und was passiert, wenn doch keine Daten da sind? Du hast also einen
usleep() eingebaut, der bei korrekter Programmierung unnötig wäre, und
die korrekte Funktion basiert allein auf dem Prinzip Hoffnung.
1
printf("%s das ist angekommen\n",angekommen);
angekommen ist kein String! Bestenfalls stehen da nach deiner Aussage
die selben Daten drin, die du verschickt hast. Da fehlt ein Null-Byte
zum Abschluss des Strings, und die Zeichen sind in ASCII "STX SOH DEL
??? ETX" (0x80 ist in reinem ASCII nicht definiert) und nichts davon
sind sichtbare Zeichen. Kein Wunder, dass da immer Müll rauskommt.
1
if(status!=num){
2
printf("write failed weil != sizeof textlänge\n");
3
}
Das ist kein Fehler, sondern ganz normaler Betrieb.
arbeite auch nicht nicht-blockierend. Wahrscheinlich braucht das Gerät
am anderen Ende der Leitung einfach die Zeit um den Antwortstring zu
generieren und zu schicken
Wäre nicht-blockierend besser? Die Gegenhardware muss doch erstmal
lauschen, verarbeiten und sendet dann erst.
Jedenfalls geht es jetzt. Danke für die Hilfe
VT0815 schrieb:> Wäre nicht-blockierend besser?
kommt daruf an. Unter linux gibt es für die serielle schnittstelle kein
möglichkeit einen Timeout festzulegen. Damit würde das Programm
blockiern weil eventuell NIE etwas kommt. Da muss man wohl oder übel mit
non-block arbeiten. Aber dann sollte man die Abfrage ob etwas da ist mit
select oder poll vorher machen, dort kann man dann den Timeout
übergeben.
while( !alles gelesen ) {
if ( select ( fd ..., timeout ) == timeout ) {
FEHLER;
}
read(fd ... )
}
so in der Art ist es ohne sleep sauber.
Aber man kann doch mit c_cc [VTIME] einen Timeout festlegen, auch wenn
man blockierend arbeitet?
Lass die NONBLOCk Option jetzt aber doch gesetzt. Und deinen Vorschlag
mit dem Polling werde ich auch mal ausprobieren.
VT0815 schrieb:> Aber man kann doch mit c_cc [VTIME] einen Timeout festlegen, auch wenn> man blockierend arbeitet?
ja, aber das wirkt glaube ich nicht wirklich.
> Und deinen Vorschlag> mit dem Polling werde ich auch mal ausprobieren.
ist es kein polling
2 der größten Mysterien in der ganzen Programmierung
* warum können Computer nicht in die Zukunft sehen, um zu wissen
wieviele Bytes ihr Gegenüber noch schicken wird?
* warum benötigt auch eine Datenübertragung Zeit, die dann auch noch
gemeinerweise um Größenordnungen langsamer ist, als die heutigen
Gigaherz-Boliden rechnen können?
Die Antwort auf beide Fragen, liefert dir die Begründung warum ein
deartiges read nicht funktioniert.
1
status=read(fd,angekommen,nbytes);//readbefehl, status ist anzahl der gelesenen bytes
der Kommentar ist falsch bzw. missverständlich. Das sind in dem Fall,
dass von der UART gelesen werden soll, die Bytes die schon am PC
eingetrudelt sind. Ob das alle Bytes sind, der der Empfänger sich
anschickt auch wegzuschicken, ist damit noch lange nicht gesagt. read
liefert das was da ist. Nicht mehr und nicht weniger. Ob einige der
Bytes, die ser Empfänger wegschickt noch mit dem berittenen Boten
unterwegs sind oder vieleicht gar noch gar nicht auf den Weg gebracht
wurden, kann read nicht wissen. Also gibt es dir erst mal das, was da
ist.