Auch mal ein kleines Tutorial von mir, da ich die Anforderung hatte, lange gesucht habe und dann doch ganz erfolgreich gelöst habe. Hier mein Weg:
Einleitung
Ziel ist es, die serielle Schnittstelle zum Datenübertragen zu benutzen. Speziell bei mir geht es darum, aus einer Paketwaage das Gewicht zu lesen.
Erste Anlaufstelle und Suche war natürlich
www.delphi-forum.de und
www.dsdt.info. Mein erster Versuch mit den Beispielen von
SchelmVomElm ist leider gescheitert. Also bin ich weiter auf die Suche gegangen und habe SerialNG von Domis gefunden:
www.domis.de/serialng.htm Das ist Freeware mit Quelltext. Und damit hat es sofort funktioniert.
Die Komponente SerialNG ist Objektorientiert und beinhaltet als Main-Klasse TSerialPortNG. Nach dem Instanziieren wird Port und Baud-Rate eingetragen und aktiviert. Die Klasse erstellt sofort einen Thread, welcher im Hintergund die Schnittstelle permanent liest. Ausserdem gibt es ein entsprechendes Event, welches den Empfang von Daten signalisert. Der Datenempfang erfolgt also permanent in einen Puffer, welchen man als Benutzer einfach abfragen kann.
Die Komponente SerialNG kann auch als No-Gui-VCL Komponente installiert werden, die entsprechenden Anleitungen sind auf der Homepage. Ich habe mir das aber alles einfach gespart, die serialng.pas ins Projekt aufgenommen, im uses eingebunden und los.
Soviel zur Theorie, nun zur Praxis:
Ich gehe davon aus, dass Du ein Projekt hast, bei dem Du irgendwann auf die Stelle triffst, "jetzt will ich Daten an COM1 schicken" bzw. "jetzt sollte ich die Daten von COM1 haben".
1. COM1 öffnen und schliessen
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| procedure machwas; var port: TSerialPortNG; begin port := TSerialPortNG.Create(nil); try port.CommPort := 'COM1'; port.BaudRate := 9600; port.Active := true; machwas2(port);
finally port.Active := false; freeandnil(port); end; end; |
2. Daten an Schnittstelle senden
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure machwas2(port: TSerialPortNG); var text: String; begin text := 'gib mir dein gewicht'; port.SendString(text + #13);
machwas3(port); end; |
3. Daten empfangen
Daten empfangen geht auf zwei Wegen.
a) man registriert eine Funktion am Event OnRxClusterEvent oder
b) man wartet selbst auf die Daten.
a) eignet sich für z.B. einen Chat, wo beide Seiten wild durcheinander senden.
b) ist eher für einen Server nach dem Model: ich schicke einen Befehl und warte auf die Antwort. Das ist das, was wir hier tun.
Ach so: Cluster ist einfach nur ein Name für einen Brocken empfangener Daten. Ich habe den Namen nicht ausgesucht, ist aber nichts gefährliches.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
| procedure machwas3(port: TSerialPortNG); var buffer: String; timeout: integer; abgelaufen: TDateTime; datenok: boolean; begin buffer := ''; datenok := false; timeout := 2000 abgelaufen := IncMilliSecond(getTime(), timeout); while (getTime() <= abgelaufen) and (not datenok) do begin
if port.nextClusterSize > 0 then begin buffer := buffer + port.ReadNextClusterAsString(); end;
if copy(buffer, length(buffer), 1) = #13 then begin datenok := true; end;
sleep(50); end;
if datenok then begin machwas4(buffer); end; end; |
Die Prozedur liesst also 2 Sekunden lang alle Daten die ankommen. Sind die Daten angekommen, die Du erwartet hast (hier: das letzte zeichen ist ein CR) hört die Schleife auf und gib die Daten weiter. Diese Methode machwas4 definieren wir mal als "vorhanden". Bei mir analysiert diese Methode das erhaltene Gewicht, konvertiert es in einen double und schreibt es in ein Formular.
Kritische Stellen
Durch die Schleife steht dein System mindestens 0,05s maximal 2s und reagiert nicht mehr. Es macht also Sinn, das ganze in einen Thread zu packen. Das war bei mir nicht nötig, da das ganze sowieso in einem Thread ist (der das Gewicht dauern liesst). Das sollte aber auch nicht schwer fallen. Aber bitte das Synchonize beim Schreiben ins Formular nicht vergesssen!
Die Bedingung "habe genug Daten erhalten" sieht so primitiv aus, hat es aber in sich. Nämlich die Frage: Woher weiss ich, wann ich genug empfangen habe. In meinem Fall was das vorgegeben, die Waage beginnt mit einem : und endet mit einem #13. Für alle anderen heisst es "Schnittstelle definieren". Möchtest Du beispielsweise zwei Rechner zusammenschliessen und Deine Daten als XML übertragen (ja, das ist möglich), wäre ein #13 ungeeignet, da das innerhalb der Daten vorkommt. Hier bietet sich eines der Steuerzeichen als Ersatz an, z.B. #0, #1, usw. Aber die Gegenstelle muss das dann aber auch senden.......
Dieses Werk ist unter einer Creative Commons 3.0 Lizenz lizenziert und darf unter Namensnennung kopiert, weitergegeben, veröffentlicht und verändert werden.