Hi, wie kann ich in C programmieren, dass der Eingabepuffer abgefragt wird, ob sich dort noch Daten befinden? if (weitere Daten vorhanden?) { lies ein Zeichen von Seriell ein } Gruß R.
Zusatzfrage: Gibt es überhaupt einen Puffer? Wie groß ist er?
Du musst die Schnittstelle im NONBLOCKing modus öffnen. Dann gibt er dir beim lesen genau so viele bytes zurück, wie er im puffer hat.
Wenn ich die Zeichen byteweise einlese, dann komme ich irgendwann an einen Punkt, wo keine Zeichen mehr zur Verfügung stehen. Das Programm hängt bei 'read(port, buffer, 1)'.
Raptor schrieb: > Wenn ich die Zeichen byteweise einlese, dann komme ich irgendwann an > einen Punkt, wo keine Zeichen mehr zur Verfügung stehen. > > Das Programm hängt bei 'read(port, buffer, 1)'. Quellcode ?
Der Quellcode sieht im Moment so aus:
1 | for (x=0; x<30; x++) |
2 | {
|
3 | // Jetzt können Daten gelesen werden
|
4 | bytes = read(port, buffer, sizeof(buffer)); |
5 | printf(buffer); |
6 | if (buffer[0] == '\n') |
7 | {
|
8 | break; |
9 | }
|
10 | }
|
Wenn aus irgendeinem Grund weniger als 30 Zeichen und kein '\n' geliefert werden, dann hängt das Programm an dieser Stelle. Was kann ich dagegen machen?
Die serielle Schnittstelle muss auch richtig konfiguriert werden, Rest siehe: http://tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html P.S.: Ich vermute mal, dass du auch select verwenden möchtest.
Ja, ich habe die Schnittstelle auch initialisiert:
1 | // serielle Schnittstelle für die Kommunikation zum Arduiono öffnen
|
2 | // beim Arduino wird dadurch ein RESET durchgeführt, Grund: DTR geht auf LOW
|
3 | port = open(COM_DEVICE, O_RDWR); |
4 | // prüfen, ob die Schnittstelle erfolgreich geöffnet wurde
|
5 | if (port == -1) |
6 | { // das ist der Fehlerfall |
7 | printf("Schnittstelle konnte nicht geöffnet werden.\n"); |
8 | return(1); |
9 | }
|
10 | // Geschwindigkeit einstellen und sonstige Einstellungen
|
11 | if (tcgetattr(port, &com_attr)!= 0) |
12 | {
|
13 | printf("Schnittstelle fehlerhaft: tcgetattr()"); |
14 | return(1); |
15 | }
|
16 | // jetzt die Einstellungen
|
17 | com_attr.c_cflag = COM_SPEED | CS8 | CRTSCTS | CLOCAL | CREAD; |
18 | com_attr.c_iflag = 0; |
19 | com_attr.c_oflag = OPOST | ONLCR; |
20 | com_attr.c_lflag = 0; |
21 | if (tcsetattr(port,TCSAFLUSH, &com_attr) != 0) |
22 | {
|
23 | printf("Schnittstelle fehlerhaft: tcsetattr()"); |
24 | }
|
Was ist 'select'? Ist das das Zauberwort? Ich werde es mir mal ansehen.
Raptor schrieb: > port = open(COM_DEVICE, O_RDWR); durch port = open (COM_DEVICE; O_RDWR | O_NONBLOCK); ersetzen. block schrieb: > Dann gibt er dir > beim lesen genau so viele bytes zurück, wie er im puffer hat.
Raptor schrieb: > Wenn aus irgendeinem Grund weniger als 30 Zeichen und kein '\n' > geliefert werden, dann hängt das Programm an dieser Stelle. > > Was kann ich dagegen machen? Es "hängt" nicht, sondern es blockiert. Es wartet auf ein Zeichen. Du hast ja immerhin mit read() gesagt, daß das nächste Zeichen gelesen werden soll. Wenn keins da ist, wird halt gewartet, bis eins da ist. Wo soll es auch sonst herkommen? Raptor schrieb: > Was ist 'select'? Ist das das Zauberwort? Ich werde es mir mal ansehen. Kommt drauf an, was du denn nun genau tun willst. Mit select() kannst du auf eine oder mehrere Dateien/Geräte/Sockets mit Timeout warten. Wenn du also das Warten nach einer bestimmten Zeit abbrechen willst, gige das mit select().
poll ist heutzutage eher der passende Call. Das hilft aber nicht gegen das Blockieren, wenn man danach mehr als ein Zeichen lesen will. D.h. man sollte mit NONBLOCK öffnen und dann zur Vermeidung von zeitfressenden Schleifen (weil read immer mit -1 zurückkommt) mit poll feststellen, ob was da ist und sonst einfach Zeit (aber nicht CPU...) verbraten.
Ehrlich gesagt habe ich den Anwendungszweck das nichtblockierenden Lesens noch nie so richtig verstanden. Wenn ich von irgend was Daten will, dann warte ich doch so lange, bis diese da sind. Will ich parallel was anderes machen, benutze ich Threads. was bringt das "Ich lese nichtblockierend und wenn nix da war, warte ich". Das ist doch auch nur blockierendes Lesen in kompliziert.
> Ehrlich gesagt habe ich den Anwendungszweck das nichtblockierenden > Lesens noch nie so richtig verstanden. Wenn man zB. nicht weiss, wie lange die Message ist, die da eigentlich so reinkommt... Entweder popele ich dann jedes einzelne Byte aus dem Device (naja, ginge bei RS232 noch so) oder man nimmt alles, was man bekommen kann aber ohne das Warten auf das Füllen des Gesamtbuffers... > Will ich parallel was anderes machen, benutze ich Threads. Die helfen gegen obiges Problem nicht.
Vlad Tepesch schrieb: > Ehrlich gesagt habe ich den Anwendungszweck das nichtblockierenden > Lesens noch nie so richtig verstanden. Wenn ich von irgend was Daten > will, dann warte ich doch so lange, bis diese da sind. Will ich parallel > was anderes machen, benutze ich Threads. Für sowas muß man doch nicht gleich mit Threads und deren Synchronisation hantieren. Einen Thread zu erzeugen, der dann quasi nichts anderes tut, als blockierend auf Daten zu warten, finde ich irgendwie unsinnig. Und nun müssen die Daten auch wieder irgendwie vom Lese-Thread in den anderen Thread kommen, und dann habe ich wieder das gleiche Problem. > was bringt das "Ich lese nichtblockierend und wenn nix da war, warte > ich". Das ist doch auch nur blockierendes Lesen in kompliziert. Es sei denn, ich erwarte eine bestimmte Menge Daten, will aber nicht bis zum Sanktnimmerleinstag warten, wenn doch mal nicht alles ankommt. read() hat halt keine Möglichkeit einen Timeout anzugeben, select() schon. Wenn man das benutzt, muß man aber darauf achten, daß es nicht passieren kann, daß read() doch mal blockiert, also öffnet man das Gerät non-blocking und wartet dann nur im select().
select() hat vor allem den Vorteil, dass bei mehreren Streams gleichzeitig warten kann, ob etwas ankommt, um dann nur bei dem, bei dem was angekommen ist, read() aufrufen zu müssen. Wobei einer der Streams natürlich auch stdin o.ä. sein kann.
Du kannst Dir auch bevor "read" ausgeführt wird die Anzahl der Bytes im Puffer mittels ioctl abholen, ist recht nützlich!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.