Forum: PC-Programmierung Serielle Schnittstelle abfragen


von Thomas W. (wenzelt)


Lesenswert?

Hallo,
ich habe ein Problem mit dem Lesen der seriellen Schnittstelle. Ich 
schreibe zunächst einen Befehl auf die serielle Schnittstelle:

write(s16_fd_Spektrometer, ac8_sendstring, u16_length);

Danach warte ich per Select auf die Antwort des Spektrometers:

s16_retval = select(s16_fd+1,&st_rfds, NULL, NULL, &st_tv);

Sobald mein Thread wieder erwacht wird wie üblich geprüft, ob ein 
Timeout stattgefunden hat oder ob tatsächlich Daten vorhanden sind. Dort 
kommt es zu meinem Problem. Select meldet bei Linux das erste ankommende 
Byte, bei einer langsamen Übertragungsrate purzeln die Bytes danach noch 
weiter ein (im Falle meines Spektrometers dann auch nicht stetig). Dies 
führt dazu, dass ein Lesen der Schnittstelle manchmal zu einer 
unvollständigen Antwort führt.

s16_retval_2=read(pst_info->s16_device,&ac8_receive_string,1200);

Danach gehe ich aus dem Thread wieder raus und sende den nächsten 
Befehl, der als Antwort oftmals noch Reste des Puffers der Antwort 
vorher enthält.

Kann man read() oder select() dazu bringen zu warten bis eine Endkennung 
des Empfangsstrings eintrudelt (in meinem Fall ein '!' oder '*'))?

Danke!

von Oliver R. (superberti)


Lesenswert?

Hi,

weder read() noch select() kennen irgendein Textende. Wenn Du nicht im 
voraus weißt, wie lang Dein gesendeter String wird, dann bleibt Dir 
nichts anderes übrig, als immer nur ein Byte in einer Schleife zu lesen:

while (!Endekennung)
{
  select(...)
  read(nur ein byte)
  ...
}

Gruß,

Oliver

von Peter II (Gast)


Lesenswert?

Oliver R. schrieb:
> dann bleibt Dir
> nichts anderes übrig, als immer nur ein Byte in einer Schleife zu lesen:

was dann aber auch das Select in frage stellt. Warum nicht gleich read 
machen?

von juppi (Gast)


Lesenswert?

Servus,

mit dem select() und read() den Eingangspuffer bei jedem auftreten von 
select() komplett auslesen, alles zusammen weg puffern und den Puffer 
dann auf deine Endkennung durchsuchen. Funktioniert prima. Das puffern 
und parsen muss sein da du keine kontrolle über den Interupt händler im 
Kernel hast.

von Oliver R. (superberti)


Lesenswert?

Hi,

> Oliver R. schrieb:
>> dann bleibt Dir
>> nichts anderes übrig, als immer nur ein Byte in einer Schleife zu lesen:
>
> was dann aber auch das Select in frage stellt. Warum nicht gleich read
> machen?

weil der OP ein Timeout haben möchte?

Gruß,

von Peter II (Gast)


Lesenswert?

Oliver R. schrieb:
> weil der OP ein Timeout haben möchte?

unter windows geht das auch problemlos mit read, wie sie linux da 
verhält kann ich leider nicht sagen.

von Oliver R. (superberti)


Lesenswert?

Hi,

> Oliver R. schrieb:
>> weil der OP ein Timeout haben möchte?
>
> unter windows geht das auch problemlos mit read, wie sie linux da
> verhält kann ich leider nicht sagen.

read() kombiniert mit Timeout geht nicht, das Standardverhalten ist 
blockierend. Man kann zwar das Device auch non-blocking öffnen, dann 
hätte man ohne select() aber eine Busy-Loop, möchte man ja auch nicht.
Ansonsten hat juppi aber recht. Diese Methode ist am effizientesten. 
Wird aber auch durch die zusätzliche Pufferverwaltung aufwändiger.
Bei solch langsamen reads wahrscheinlich eh byte für byte.

Gruß,

von Thomas W. (wenzelt)


Lesenswert?

Hallo,
danke für die schnelle Reaktion.

Eigentlich sollte es ohne jegliches while funktionieren. Ich kann und 
will das System nicht pollen lassen, dafür ist meine kleine CPU einfach 
überlastet. Auf dem System laufen noch einige andere (zeitkritische) 
Prozesse die nicht wegen einer kleinen Abfrage der seriellen 
Schnittstelle auf 9600 baud eingebremst werden sollten.

Werde mal versuchen wie mein System auf select() und read() in einer 
while Schleife reagiert. Melde mich dann zurück...

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.