Serielle Schnittstelle

unter POSIX-Betriebssystemen programmieren

Manchmal ist es notwendig ältere Hardware an einem Rechner zu betreiben. Ich habe zum Beispiel ein digitales Oszilloskop mit einer seriellen Schnittstelle (RS232), für das ich leider nur DOS Software habe. Nachdem der letzte DOS Rechner jetzt nicht mehr ist, hab ich mir gedacht es kann ja nicht so schwer sein das Ding unter Linux zum laufen zu bringen.

Nach einem kurzen Test mit einem kleinen Perl Script wurde mir klar, dass das unter POSIX-Betriebsystemen sehr viel einfacher ist als unter DOS. Das Konzept "Alles ist eine Datei" macht es eben einfach. Man konfiguriert die Schnittstelle mit dem stty Kommando:


stty -F $PORT raw ispeed 115200 ospeed 115200 -echo

Ein Senden über die serielle Schnittstelle ist dann einfach ein Schreibvorgang in eine Datei, nämlich die Gerätedatei: /dev/ttyS0. Den Rest erledigt das Betriesbssystem. Den Empfang kann man ähnlich einfach gestalten, man leitet zum Beispiel Eingaben aus der Gerätedatei in eine Datei um und stellt diesen Prozess in den Hintergrund:


cat /dev/ttyS0 > Zieldatei &

Im Fall meines Oszilloskops brauche ich dann nur noch ein Steuerkommando Senden,


echo "N" > /dev/ttyS0

warten bis alle Daten Übertragen sind und dann den Hintergrundjob wieder killen:


kill %1

Die Empfangenen Daten stehen dann in der Zieldatei. Und das nur von der Bash aus. Nun wollte ich nicht viel Programmieren, und habe die Anzeige der Daten einfach GNUplot überlassen. Dazu musste ich dann allerdings doch ein kleines C-Programm schreiben, das die empfangenen binärdaten in ASCII umwandelt und weil es so einfach ist, macht es auch gleich noch eine DFT in eine zweite Datei. Nun wird ein GNUplot-Script die Aufgearbeiteten Daten anzeigen oder in PDF Ausgeben, hier ein Beispiel für die Messung der Stromaufnahme eines Netzwerk-switches.

Da eben alle Geräteschnittstellen durch Dateien repräsentiert werden kann man im Prinzip auf diese Weise auch USB Schnittstellen oder auch andere auf die gleiche Weise ansprechen. Mit ein paar Einschränkungen natürlich, denn ganz so einfach sieht es natürlich nicht mehr aus, wenn die Schnittstelle ein echtes Bussystem ist. Auch ist die Puffergrösse beim Schreiben im Kernel begrenzt, man kann also nicht beliebig grosse Dateien auf die Schnittstelle schieben sondern muss diese in meinem Fall in 4K Häppchen portionieren. Für mein Oszi war das allerdings nicht nötig, das ist eine einfache Punkt-zu-Punkt Kommunikation mit kuzen Kommandos aus einem oder zwei Bytes. Die zurück übertragenen Daten sind 32K gross, was aber mit der Umleitung in eine Datei kein Problem ergibt.

In Perl ist so etwas noch einfacher und die Schnittstelle direkt in C anzusprechen ist auch nicht wirklich schwierig. Das Oszi lässt sich in Grundfunktion mit nur 140 Zeilen C-Code betreiben. Je nach dem wieviel Empfangspuffer das Gerät am andern Ende der Leitung hat oder was es tun soll muss man beim Senden ein bischen aufpassen und nach Versand mal ein usleep(10000); oder ähnliches einbauen. Der Ramtest des Oszis dauert zum Beispiel 0,3s während dessen das Ding nichts mehr Empfängt. Da die serielle Schnittstelle des Oszis aber ohne Handshake läuft, kann man das nur über eine entsprechende Wartezeit berücksichtigen.

Eine weitere Spielart ist eine Umleitung eines Geräteanschlusses über eine Netzwerk auf einen entfernten Computer. socat ist alles was man braucht. In der Manpage stehen einige Beispiele die schon recht brauchbar sind.