07.12.2003 Serielle Schnittstelle und HP IPAQ 2210

Für das VStabi Programm möchte ich die serielle Schnittstelle eines IPAQs verwenden, um Daten auszutauschen. Das Programm selbst ist in JAVA geschrieben, und ich wollte daran auch nichts ändern, da mir das alles geläufig ist. Also machte ich mich auf die Suche nach Möglichkeiten.

Als JVM testete ich die JVM von SUN, die als Beta Version auch für den ARM Prozessor angeboten wird. Die Window Darstellung und der Funktionsumfang erschien mir geeignet, um das Projekt zu realisieren. Es handelt sich um eine Implementierung der Version 1.1.8 der JVM, es wird vor allem AWT unterstützt, das native Windows Funktionen für die Darstellung benutzt. Dadurch startet das Programm sehr schnell (ca 1 sec), und sieht auch einem WinCE Programm sehr ähnlich. Auch die Geräusche, die entstehen, wenn man im Menü navigiert, sind identisch.

Die Anwendung mußte gründlich umgestellt werden, da keine Swing Klassen mehr zur Verfügung stehen, sondern nur AWT. Acuh hier ist der Funktionsumfang etwas abgespeckt, aber vollkommen ausreichend. Ledier gibt es etwas unangenehme Einschränkungen bei den Scroll Panes, die etwas flackern, wenn gescrollt wird. Das ist aber nur bei wenigen Stellen nötig, so daß man gut damit leben kann.

Ein weit größeres Problem war die Ansteuerung der seriellen Schnittstelle. Die Suche nach dem javax.comm API führte in den meisten Fällen zu kostenpflichtigen JVM´s. Einige bieten eine kostenlose Testversion an, die aber wegen ihrer beschränkten Darstellungen mich nicht überzeugen konnten, andere waren nicht als Testversion verfügbar, und ohne Test kann ich das nicht kaufen.

Die einzige testbare Implementation fand ich bei James Nord auf http://www.teilo.net . Damit konnte ich tatsächlich die serielle Schnittstelle ansteuern. Leider gab es auch hier Probleme, so dass ich Kontakt zu James Nord aufnahm, und er sehr hilfsbereit antwortete!. Das wird auch weiter fortgesetzt!

Nebenbei wollte ich aber eine stabile Implementation für die serielle Schnittstelle erhalten, und so machte ich mich auf die Suche nach Alternativen.

Microsoft bietet eine kostenlose Version ihrer Entwicklungsumgebung für Win CE auf Strong ARM Prozessoren an. Das ist die wichtigste Voraussetung für die Tests. Ich implementierte nun eine Art Wrapper für die Windows File Funktionen, damit ich von Java aus das Verhalten testen kann. Es handelt sich um ein JNI (Java Native Interface), das die wichtigsten Funktionen für die Serielle Schnittstelle beinhaltet. Es entsteht eine dll, die vom Java Code aus gelesen und benutzt werden kann.

Etwas tricky ist die Erstellung des Header Files für den ARM Prozessor, denn ich konnte keine Version der jni.h für ARM bzw WinCE finden. Ich verwende einfach die Win32 Version, die tatsächlich funktioniert, solange man auf Long Parameter verzichtet.

Java Quelldatei, wird in das eigene Programm eingebunden, und dient zum erzeugen der Headerdateien
serial_function.java
DLL für Strong ARM Target, kommt in das "\Programme\java\bin" Verzeichnis
serial_function.dll
Quelle der DLL
serial_function.c

Der Einfachheit halber wurde keine Package verwendet, die Klasse gehört also ins "Root" des Projektes. Die Headerdatei kann erzeugt werden mit

javah -o serial_function.h serial_function

Man muß natürlich im Verzeichnis der java Datei sein. Die Klasse kann dann kompiliert werden mit

javac serial_function.java

Die dll habe ich mit der IDE von Microsoft erstellt, es gibt dort einen Wizzard, der entsprechende Optionen erstellt. Bei dem Include Path muß zusätzlich der Include Path der Java Umgebung mit angegeben werden bei mir war es "C:\jdk1.1.8\include,C:\jdk1.1.8\include\win32". Die Ergebnisklasse muß im Classpath der Anwendung erreichbar sein. Wird das ganze in ein Projekt eingebaut, braucht man nur die Java Datei ins Projekt einzubauen , und mitzukompilieren.

Das ganze ist mit Sicherheit nicht fehlerfrei, einen Trick mußte ich bei den Handels verwenden, denn es handelt sich in Wirklichkeit um Pointer, die sich nicht vernünftig auf Java Type abbilden lassen. Daher werden die Handels in einer kleinen Liste verwaltet, und in der dll selbst gehalten. 10 Handels für Schnittstellen sollten eigentlich reichen...

Einfachster Anwendungsfall:
Init aufrufen
CreateFile aufrufen, Filename="COM1:" (Doppelpunkt nicht vergessen!) mode=MODE_READ | MODE_WRITE
WriteFile mit dem Ergebnis von CreateFile als Handle, einem Byte Array als Buffer, und die länge der zu sendenden Dtaen aus dem Buffer.

Dann sollte schon was auf der Schnittstelle mit 9600 8N1 kommen

Empfangen kann man mit ReadFile mit ähnlichen Parametern. Das mache ich vorzugsweise in einem eigenen Thread, damit nichts blockiert wird. Das geht sehr schön auch parallel zum Senden von Daten. Interessant ist, das die Read Fiel Funktion etwa alle Sekunde zurückkommt, auch wenn nichts empfangen wurde. Ansonsten wenn der Puffer gefüllt ist.

Das war für mich bereits das perfekte Verhalten. Das Ganze ist sehr stabil, auch wenn unterwegs die Schnittstelle gewechselt wird (CloseFile, und dann CreateFile mit neuem Namen). Wird der Ipaq ausgeschaltet und wieder eingeschaltet während das Programm aktiv ist, konnte ich leider keine Vernünftige Reaktion der Error Codes erkennen. Man kann also nicth erkennen, ob  der Datensender nicht mehr aktiv ist, oder ob der Pocket PC zwischendurch ausgeschaltet wurde.
Ich habe das so gelöst, das bei fehlendem Dateneingang nach einigen Sekunden die Schnittstelle vorsorglich geschlossen und neu geöffent wird.

Bei Fragen und Ideen -> mail an mich! http://www.ulrich-roehr.de Danke!