Hi, Letztens hatte ich nach einer kleinen C-Lib gesucht, die die Ansteuerung der Seriellen Schnittstelle kapselt, so dass für Linux und Windows keine Codeanpassungen notwendig sind. Da die Suchergebnisse recht dürftig waren und das was ich gefunden (genau genommen war es nur eine Bibleothek und eine Ausarbeitung) habe nicht meinen Vorstellungen entsprochen hat, habe ich was eigenes aufgesetzt. Wichtig war mir ein blockierendes Lesen und die Möglichkeit in einem Thread blockierend zu lesen und in einem anderen schreiben zu können. Unter Windows wird dafür Overlapped IO benutzt. Unter Linux scheint es ohne weitere Maßnahmen zu funktionieren. Die Linuximplementierung gefällt mir noch nicht so richtig. Ich habe nicht so richtig rausbekommen, wie man beliebige baudraten einstellen kann. Zum anderen weiß ich nicht, wie ich das so konfigurieren kann, dass er unendlich lange blockiert, bis er alle Zeichen des read-requests bekommen hat. VTIME geht nur maximal 25s. und wenn VMIN < bytesToRead-Param der Read Funktion ist, scheint auch undefiniert zu sein, was da passiert. Deswegen wird jetzt VMIN auf 1 gestellt und im read Byteweise gelesen. Dennoch ist das Ganze insgesamt auf einem Stand, in dem es mir momentan gut ausreicht, weswegen ich jetzt erstmal auf dem Stand lasse. Wenn jemand Vorschläge/Verbesserungen hat, dann bin ich dafür offen und werde das sicherlich auch einpflegen. Gruß, Vlad
hier der Source an die mods: sollte eigentlich an den ersten Beitrag. das nachträgliche Anhängen per Editieren funktioniert nicht.
Vlad Tepesch schrieb: > das nachträgliche Anhängen per Editieren funktioniert nicht. Für uns auch nicht. :-/
vielen dank, genau so etwas habe ich gesucht!!!
Ach so, was in der Linux Implementieurung auch noch fehlt, ist die Funktion zum auflisten der verfügbaren devices. Die Möglichkeiten, die ich gefunden habe, basieren auf dem iterieren über alle /dev/ttySxx und /dev/ttyUSBxx Geräteknoten und dem Versuch diese zu öffnen. Das ist doch irgendwie Pfusch.
Vlad Tepesch schrieb: > Die Möglichkeiten, die ich gefunden habe, basieren auf dem iterieren > über alle /dev/ttySxx und /dev/ttyUSBxx Geräteknoten und dem Versuch > diese zu öffnen. Das ist doch irgendwie Pfusch. Das ist harmlos. Die Sache mit HKEY_LOCAL_MACHINE/HARDWARE/DEVICEMAP/SERIALCOMM ist ja auch nur die halbe Wahrheit. Vor einer Weile stand ich vor demselben Problem (also Schnittstellen auflisten) und habe recherchiert. Insgesamt musst du praktisch an neun verschiedenen Stellen suchen, um wirklich alle Ports zu finden: [1] http://stackoverflow.com/questions/1388871/how-do-i-get-a-list-of-available-serial-ports-in-win32 [2] http://www.naughter.com/enumser.html
Sven P. schrieb: > Die Sache mit HKEY_LOCAL_MACHINE/HARDWARE/DEVICEMAP/SERIALCOMM ist ja > auch nur die halbe Wahrheit. > [2] http://www.naughter.com/enumser.html die lib habe ich auch gefunden, fand es aber übertrieben. Was soll ich mit einer Lib, die auf neun verschiedene Art und weisen die Comports sucht? ausßerdem ist mir an der Stelle egal, wie die Methode ist, was einen Benutzer interessiert, ist ja eine Liste. Das ist der große Designfehler dieser Bibliothek. Interessant wäre genau eine Funktion oder Methode, die mir eine Liste zurückgibt. Intern kann die Lib ja meinentwegen so viele Methoden benutzen, wie sie will - die gehören nur nicht ins Interface, dass sind Interna. Sven P. schrieb: > [1] > http://stackoverflow.com/questions/1388871/how-do-... Das hab ich auch gefunden. Genau deswegen habe ich auch die letzte Variante gewählt. Für Windows gibts ja auch diese Pfuschvariante mit Namen aus "COM"+X bilden. Nur dumm, dass die Ports beliebige Namen haben können. Die com0com haben defaultmäßig ja auch total schräge bezeichnungen, die dann von den ganzen Tools, die auf die Pfuschvariante setzen nicht gefunden werden. Deswegen scheint mir das ganze auch unter Linux etwas fragwürdig. woher weiß ich denn, ob nicht nächtes Jahr eine serielle Schnittstelle auf Basis von Thunderbold erscheint, die dann /dev/ttyTB0 oder so heißt, oder irgendjemand die Geräteknoten einfach anders benennt. Es muss doch auch irgendwie anders möglich sein.
Vlad Tepesch schrieb: > die dann /dev/ttyTB0 oder so heißt, > oder irgendjemand die Geräteknoten einfach anders benennt Ich habe mich auch mal vor einiger zeit damit beschäftigt. Über /proc/tty/drivers kann man sich eine solche Liste abrufen: http://stackoverflow.com/questions/2530096/linux-how-to-find-all-serial-devices-ttys-ttyusb-without-opening-them Es werden auch ein paar Alternative angerissen über dbus/hal
Vlad Tepesch schrieb: > Interessant wäre genau eine Funktion oder Methode, > die mir eine Liste zurückgibt. Naja, dann bau doch eine draus. Für was andres ist die Bibliothek da auch garnicht gedacht gewesen. > Deswegen scheint mir das ganze auch unter Linux etwas fragwürdig. woher > weiß ich denn, ob nicht nächtes Jahr eine serielle Schnittstelle auf > Basis von Thunderbold erscheint, die dann /dev/ttyTB0 oder so heißt, > oder irgendjemand die Geräteknoten einfach anders benennt. > > Es muss doch auch irgendwie anders möglich sein. Mir käme da noch /proc/tty/drivers in den Sinn. Vielleicht lässt sich über die Major/Minor auch noch was herausfiltern. Ginge jedenfalls schneller, als alle durchzuprobieren und jeweils irgendein ioctl() drauf zu machen, welches nur bei seriellen Schnittstellen funktioniert :-} Läubi war schneller.
Läubi .. schrieb: > Über /proc/tty/drivers kann man sich eine solche Liste abrufen: Den Inhalt dieser Datei konnte ich nicht interpretieren In der Doku steht nicht mal eine Spaltenbeschreibung. Hab jetzt folgendes dazu gefunden: http://lwn.net/images/pdf/LDD3/ch18.pdf heißt das ich müsste in dieser Datei alle Einträge suchen, die in der letzten Spalte serial stehen haben? aus dem Produkt der Differenzen der beiden Paare aus den vorstehenden Spalten habe ich dann die maximale Anzahl an Geräten dieses Typs. Davor steht der Geräteknoten-Basisname Was ich jetzt neu gelernt habe, ist das Verzeichnis /sys/class/tty zusammen mit dem obigen Wissen kann ich in dem Verzechnis nach Verzeichnissen suchen, in denen der Gerätebasisname vorkommt. Läubi .. schrieb: > Es werden auch ein paar Alternative angerissen über dbus/hal das hal Zeugs scheint standardmäßig nicht installiert zu sein (und schon gar nicht auf einem kleinen embedded device
Also "so einfach" ist das halt nicht machbar. Ich würde da pragmatisch vorgehen und das erst mal so implementieren das es auf deinen Zielgeräten zufriedenstellende Ergebnisse liefert. Du kannst das ja hier auch noch ins SVN stellen, dann kann man das immer weiter verfeinern. Vlad Tepesch schrieb: > das hal Zeugs scheint standardmäßig nicht installiert zu sein s.o. man kann versuchen das als zusätzliche Option einzubauen, letzendlich wird man aber auch wieder auf viele Optionen kommen welche man durchprobieren muss. Ein paar passende Compileschalter für verschiedene Targets wirds vermutlich eh brauchen...
hier eine Version 0.4 hab obigen Ansatz zum Finden von seriellen Geräten unter Linux mal implementiert. wär toll, wenn ihr das mal bei euch auch mal testen könntet. dann gabs noch eine kleine Interface-Änderung für die Funktion zum ermitteln der vorhandenen Seriellen Interfaces. PortableSerialLib - Change Log ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * fixed ~ changed + added - removed v0.4 ~ PSerLib_getAvailablePorts + added linux implementation for PSerLib_getAvailablePorts + added define for format of PSerLib_getAvailablePorts-Output (full path or just name) ~ changed interface of PSerLib_getAvailablePorts function to get additional pointer parameter to output number of found devices and return a error code.\n --> more consistency to all other functions. ~ more precise description of o_name parameter PSerLib_getAvailablePorts ~ set default baud rate of example/test program to a standard baud rate value
Vlad Tepesch schrieb: > Wichtig war mir ein blockierendes Lesen [...] Du meinst wohl eher nicht-blockierendes Lesen, oder? Oder ein blockierendes Read mit Timeout? > VTIME geht nur maximal 25s. und wenn VMIN < bytesToRead-Param der Read > Funktion ist, scheint auch undefiniert zu sein, was da passiert. Du willst einen Timeout implementieren? Nimm select(). Wenn Du weitere Fragen/Unklarheiten zur seriellen Schnittstelle unter Linux hast, frag mich einfach. Ich kenne die TTYs aus dem Effeff :-) Gruß, Frank
Frank M. schrieb: > Du meinst wohl eher nicht-blockierendes Lesen, oder? nö, ich mein es so, wie ich es geschrieben habe. Ich will einfach einen Thread dafür abstellen, auf ewig auf Input von der uart zu warten.
Hi Vlad Thanx for the nice library However i have a small improvement suggestion I have been using the library with an Arduino , and was always triggering an Arduino Reset when using your lib. I have traced it to this function in PortableSerialLibLinux.c
1 | if( (tcsetattr(io_port->port, TCSANOW, &newSettings) < 0) |
2 | || (cfsetispeed(&newSettings, speed) < 0) |
3 | || (cfsetospeed(&newSettings, speed) < 0)) |
4 | {
|
5 | return PSL_ERROR_configurePort; |
6 | }
|
And changing it to
1 | if( (cfsetispeed(&newSettings, speed) < 0) |
2 | || (cfsetospeed(&newSettings, speed) < 0) |
3 | || (tcsetattr(io_port->port, TCSANOW, &newSettings) < 0)) |
4 | {
|
5 | return PSL_ERROR_configurePort; |
6 | }
|
Solves the problem. Before filling data in the struct , you zero'es the struct.
1 | memset(&newSettings, 0, sizeof(newSettings)); /* clear the new struct */ |
But according to this , setting a speed/baud to 0 (Seek B0), will clear DTR http://www.easysw.com/~mike/serial/serial.html http://homepages.cwi.nl/~aeb/linux/man2html/man3/termios.3.html And in your code you call tcsetattr , before setting the speed , so the speed is zero , causing a DTR reset. In my example i set the speed before calling tcsetattr , and now the Arduino isnt reset on opening the SerialPort. Hope you will correct the nice library Regards Karsten Dänemark
Hi Karsten, thank you for your feedback. you are right, the linux part is not very well testet. I only used it on my fritzbox (dsl-router) to communicate over an usb uart adapter with some homemade device. please could you post the complete changed file? best regards vlad
Hi Vlad Here is the new file & a diff file Regards Karsten
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.