Serielle Schnittstelle abfragen

OP #3010100
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!
#3010421
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
Gast #3010463
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.
#3010486
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ß,
OP #3010503
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...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren