Bei der Suche nach einem Plattform-übergreifenden Zugang auf die
serielle Schnittstelle bin ich auf Synaser gestoßen. Die ersten
Versuche habe ich unter Windows getestet. Unter
https://github.com/marado/synapsel findet Synapse von Marado, eine
große Sammlung diverser Schnittstellen-Units, die nicht installiert
werden müssen. Vielmehr kopiert man einfach die benötigten Dateien aus
dem Verzeichnis synapse-master in sein eigenes Projektverzeichnis.
Entscheidend ist die Datei synaser.pas. Diese greift aber ihrerseits
auf weitere Units zurück, die ebenfalls eingefügt werden müssen.
In meinem ersten Versuch habe ich ein neues Projekt mit dem Namen
SerialSynaser gebildet. Die markierten .pas- und .ppu-Dateien musste
ich einfügen, die .o-Dateien sind beim Kompilieren entstanden. Dass das
kompilierte Programm am Ende SeriealSyaser.exe (ohne n) heißt, beruht
auf einem Tippfehler, der sich im ganzen Test gehalten hat.
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls,
synaser;
type
{ TForm1 }
TForm1 = class(TForm)
ButtonSend: TButton;
EditText: TEdit;
MemoLog: TMemo;
TimerRx: TTimer;
procedure ButtonSendClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure MemoLogAltChange(Sender: TObject);
procedure TimerRxTimer(Sender: TObject);
private
Ser: TBlockSerial;
procedure OpenPort;
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Ser := TBlockSerial.Create;
//Ser.RaiseExcept := True; // Fehler als Exception ausgeben
TimerRx.Interval := 100; // alle 100 ms prüfen
TimerRx.Enabled := True;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
TimerRx.Enabled := False;
Ser.Free;
end;
procedure TForm1.TimerRxTimer(Sender: TObject);
var
S: string;
begin
if not Ser.InstanceActive then
Exit;
if Ser.CanReadEx(0) then
begin
S := Ser.RecvString(10); //RecvPacket(0); // alle gerade verfügbaren Bytes lesen
//if (Ser.LastError = 0) and (S <> '') then
MemoLog.Lines.Add('RX: ' + S);
end;
end;
procedure TForm1.OpenPort;
begin
if not Ser.InstanceActive then
begin
Ser.Connect('COM4');
// unter Linux z.B. '/dev/ttyUSB0'
Ser.Config(1000000, 8, 'N', 0, False, False);
end;
end;
procedure TForm1.ButtonSendClick(Sender: TObject);
var
S: string;
begin
try
OpenPort;
Ser.DTR := True;
S := EditText.Text + #13#10; // CR/LF anhängen
Ser.SendString(S);
MemoLog.Lines.Add('Gesendet: ' + EditText.Text);
except
on E: Exception do
ShowMessage('Fehler: ' + E.Message);
end;
end;
end.
Es funktioniert einwandfrei mit COM 4 und 1 MBaud. Zum Test habe ich
einen FT232 angeschlossen und die Anschlüsse TXD und RXD direkt
verbunden. Wenn ich einen Text absende, wird er einen Moment später
wieder empfangen und angezeigt.
Übertragung auf den RPi 4
Das gesamte unter Windows erzeugte Verzeichnis konnte auf den RPi 4
übertragen werden. Die einzige Änderung betraf den Namen der
Schnittstelle. Sie heißt hier '/dev/ttyUSB0'. Ich musste aber erst
verstehen, dass dies die erste USB/Serielle Schnittstelle ist, die man
an einer der vier möglichen USB-Buchsen angeschlossen hat. Wenn ich
dagegen nacheinander mehrere Anschlüsse teste, bilde ich jedes Mal eine
neue Schnittstelle. Also musste ich alles noch einmal neu starten und
dann den gewählten Anschluss beibehalten.
Das Programm sollte auf unterschiedlichen RPis und mit
unterschiedlichen USB/Seriell-Wandlern funktionieren, ich konnte aber
nur mit meinen Geräten testen. Über Rückmeldungen würde ich mich
freuen, wo funktioniert es und wo nicht.