unit uCOMPort;
interface
uses Windows, SysUtils;
const
//--Konstanten für den Statusreport------------------------------------------------------------
parity : array[0..4] of String = ('Keine','Ungerade','Gerade','Markierung','Leerzeichen');
stopbits : array[0..2] of String = ('1','1,5','2');
//---------------------------------------------------------------------------------------------
//--Konstanten zum einfachen Setzen der Portflags----------------------------------------------
dcb_Binary = $00000001; // Binärer Modus - In Windows immer auf 1!
dcb_ParityCheck = $00000002; // Paritätsüberprüfung
dcb_OutxCtsFlow = $00000004; // CTS Flusskontrolle - Sendekontrolle mit Hilfe von CTS
dcb_OutxDsrFlow = $00000008; // DSR Flusskontrolle - Sendekontroll mit Hilfe von DSR
dcb_DtrControlDisable = $00000000; // DTR Flusskontrolle - Schließt DTR auf 0 bei Verbindung und hält es auf 0
dcb_DtrControlEnable = $00000010; // DTR Flusskontrolle - Öffnet DTR auf 1 bei Verbindung und hält es auf 1
dcb_DtrControlHandshake = $00000020; // DTR Flusskontrolle - Handshake-Funktion.
dcb_DtrControlMask = $00000030;
dcb_DsrSensitvity = $00000040; // Zustandsänderung auf DSR überwachen
dcb_TXContinueOnXoff = $00000080; // Stellt ein, ob die Übertragung bei XOff angehalten wird oder nicht
dcb_OutX = $00000100; // Flusskontrolle mit XOn/XOff beim Senden
dcb_InX = $00000200; // Flusskontrolle mit XOn/XOff beim Empfangen
dcb_ErrorChar = $00000400; // Bestimmt, ob Bytes mit falscher Parität durch den Error-Char ersetzt wird.
dcb_NullStrip = $00000800; // Null-Bytes werden beim Empfangen ignoriert
dcb_RtsControlDisable = $00000000; // RTS-Flusskontrolle - Schließt RTS auf 0 bei Verbindung und hält es auf 0
dcb_RtsControlEnable = $00001000; // RTS-Flusskontrolle - Öffnet RTS auf 1 bei Verbindung und hält es auf 1
dcb_RtsControlHandshake = $00002000; // RTS-Flusskontrolle - Handshake-Funktion
dcb_RtsControlToggle = $00003000; // RTS-Flusskontrolle - RTS ist an wenn Bytes zu senden sind, wenn keine zu senden sind ist RTS auf 0
dcb_RtsControlMask = $00003000; // RTS-Flusskontrolle
dcb_AbortOnError = $00004000; // Wenn ein Fehler auftritt, stoppt jede Transmission und der
// Fehler muss mit Hilfe von ClearCommError beseitigt werden.
dcb_Reserveds = $FFFF8000; // Reserviert! Nicht benutzen!
//------------------------------------------------------------------------------------------------------------------------
type TComPort = class
private
PortHandle : Integer; // Handle (u.a. Zeiger) auf den COM-Port.
DCB : TDCB; // Data-Control-Block-Struktur zum Kontrollieren der Parameter der seriellen Schnittstelle
procedure GetDCB;
procedure SetParity (Parity : byte); // Den Modus der Paritätskontrolle:
function GetParity : byte; // 0 = Keine, 1=ungerade, 2=gerade, 3=Merkierung, 4=Leerzeichen
procedure SetBaudRate (Baudrate : Word); // Setzt die Übertragungsgeschwindigkeit des Ports in Baud
function GetBaudrate : Word;
function GetStopBits : byte; // Setzt die Anzahl der Stopbits
procedure SetStopBits (bits : byte); // 0 = 1 Stopbit, 1 = 1.5 Stopbits, 2 = 2 Stopbits
function GetByteSize : byte; // Fragt die Anzhal der Bits/Byte ab.
procedure SetByteSize (bytesize : byte); // Setzt die Anzahl der Bits/Byte (Standard: 8)
public
function OpenCOM (Port : pchar) : Integer; // Öffnet COM-Port (Parameter-Beispiel: 'COM1')
procedure CloseCOM; // Schließt das Handle für den COM-Port
//-------------------------------------------Ausgaben - Indikatoren für angeschlossene Geräte
procedure TXD (State : integer); // TxD = Sendeleitung --> Hier Prozedur für Dauerspannung auf TxD
procedure RTS (State : integer); // "Request-To-Send" --> Computer signalisiert, dass er senden möchte
procedure DTR (State : integer); // "Data-Terminal-Ready" --> Computer ist bereit
//-------------------------------------------Eingaben - Indikatoren für bestimmte Ereignisse.
function CTS : integer; // "Clear-To-Send" --> Dem Computer wird angezeigt,
// dass das angeschlossene Gerät bereit ist Daten zu emfpangen
function DSR : integer; // "Data-Set-Ready" --> Angeschlossenes Gerät ist bereit
function RI : integer; // "Ring-Indicator" --> Klingelzeichen, ähnlich beim Telefon
function DCD : integer; // "Data-Carrier-Detect --> Computer ist bereit Daten zu empfangen
function INPUTS : integer;
//--------------------------------------------------------------------------------------------
function GetHndl : Integer; // Gibt das geöffnete Handle des Ports zurück
//--------------------------------------------------------------------------------------------
function GetFlags : Integer; // Fragt die Port-Flags ab.
function SetFlags (Flag : Integer; Enable : Boolean) : boolean; //Setzt die Port-Flags (siehe weiter oben)
//------------------------------------------Sendefunktionen-----------------------------------
procedure BufferSize (Size : Integer); // Setzt die Größe des Sende- und Empfangspuffers für Zeichenübertragungen
function CharInTXBuffer : Cardinal; // Aktuelle Länge des Sendepuffers
function CharInRXBuffer : Cardinal; // Aktuelle Länge des Empfangspuffers
procedure ClearBuffer; // Sende- und Empfangspuffer werden gelöscht
procedure SENDBYTE (Dat: Integer); // Byte über die serielle Schnittstelle senden
procedure SENDSTRING(Buffer: Pchar); // Text über die serielle Schnittstelle senden
function READBYTE() : Integer; // Byte über die serielle Schnittstelle empfangen
function READSTRING() : Pchar; // Text über die serielle Schnittstelle empfangen
procedure Timeouts (TOut : Integer); // Setzt die Timeouts zum Senden
function GetStatusReport : String; // Gibt einen ausführlich formulierten Statusreport des Ports zurück.
//---------------------------------------------------------------------------------------------
//-------------Eigenschaftsfestsetzungen - zum leichteren Setzen der Porteigenschaften---------
property Parity : byte read GetParity write SetParity;
property BaudRate : Word read GetBaudRate write SetBaudRate;
property StopBits : byte read GetStopBits write SetStopBits;
property ByteSize : byte read GetByteSize write SetByteSize;
//*********************************************************************************************
destructor Destroy; override;
constructor Create (AutoInit : Integer);
//*********************************************************************************************
end;
implementation
constructor TComport.Create (AutoInit : Integer);
begin
case AutoInit of
1 : OpenCOM('COM1');
2 : OpenCOM('COM2');
end; {CASE}
end;
function TComPort.OpenCOM (port : pchar) : Integer;
var
PortStr, Parameter : String;
begin
Result := 0;
// Wenn Port-Handle geöffnet, dann Handle schließen
if PortHandle > 0 then CloseHandle(PortHandle);
// übermittelter COM-Port 'herausfiltern'
Parameter := port;
PortStr := copy(Parameter,1,4);
// COM-Port öffnen
PortHandle := CreateFile (PChar(PortStr), GENERIC_READ or GENERIC_WRITE,
0,nil,OPEN_EXISTING,0,0);
//Status des Ports überprüfen und DCB-Struktur füllen
GetCommState(PortHandle,dcb);
//DCB-Struktur mit Standardwerten füllen
BuildCommDCB(PChar(Parameter),dcb);
//Eigene Flags setzen
DCB.Flags := 1;
//Änderungen auf den Port anwenden und auf Erfolg überprüfen
if SetCommState (PortHandle, DCB) then Result := 1;
end;
procedure TComPort.CloseCOM;
begin
//Port schließen und Handle zurücksetzen (wegen OpenCOM!)
GetCommState(PortHandle,dcb);
SetParity(0);
SetBaudrate(1200);
SetStopBits(0);
SetByteSize(8);
SetCommState(PortHandle,dcb);
CloseHandle(PortHandle);
PortHandle := 0;
end;
procedure TComport.TXD (State: Integer); //TxD bei 0 auf Sendemodus stellen, bei 1 auf Dauerspannung (Sendebetrieb nicht möglich)
begin
if State=0 then
EscapeCommFunction(PortHandle,CLRBREAK)
else
EscapeCommFunction(PortHandle,SETBREAK);
end;
procedure TComPort.RTS (State:Integer); //RTS entweder auf 0 oder auf 1 setzen
begin
if State=0 then
EscapeCommFunction(PortHandle,CLRRTS)
else
EscapeCommFunction(PortHandle,SETRTS);
end;
procedure TComPort.DTR (State : integer); //DTR entweder auf 0 oder 1 setzen
begin
if State = 0 then
EscapeCommFunction(PortHandle,CLRDTR)
else
EscapeCommFunction(PortHandle,SETDTR);
end;
function TComPort.CTS : Integer; //CTS auf Status abfragen
var
mask : DWord;
begin
GetCommModemStatus(PortHandle,mask);
if (mask and MS_CTS_ON) = 0 then
result := 0
else
result := 1;
end;
function TComPort.DSR : Integer; // DSR auf Status abfragen
var
mask : DWord;
begin
GetCommModemStatus(PortHandle,mask);
if (mask and MS_DSR_ON) = 0 then
result := 0
else
result := 1;
end;
function TComPort.RI : Integer; // RI auf Status abfragen
var
mask : DWord;
begin
GetCommModemStatus(PortHandle,mask);
if (mask and MS_RING_ON) = 0 then
result := 0
else
result := 1;
end;
function TComPort.DCD : Integer; // DCD auf Status abfragen
var
mask : DWord;
begin
GetCommModemStatus(PortHandle,mask);
if (mask and MS_RLSD_ON) = 0 then
result := 0
else
result := 1;
end;
function TComPort.Inputs : Integer;
var
mask : DWord;
begin
GetCommModemStatus(PortHandle,mask);
result := (mask div 16) and 15;
end;
function TComPort.GetHndl : integer;
begin
result := PortHandle;
end;
procedure TComPort.SetParity (Parity : byte);
begin
if (PortHandle > 0) and (Parity in [0..4]) then
begin
GetDCB;
DCB.Parity := Parity;
windows.SetCommState(PortHandle,DCB)
end;
end;
function TComport.GetParity : byte;
var
temp : TDCB;
begin
if (PortHandle > 0) then
begin
GetCommState(PortHandle,temp);
result := temp.Parity;
end
else
result := 255;
end;
function TComport.GetBaudrate : Word;
var
temp : TDCB;
begin
if (PortHandle > 0) then
begin
GetCommState(PortHandle,temp);
result := temp.BaudRate;
end
else
result := 0;
end;
procedure TComPort.SetBaudRate(Baudrate : Word);
begin
if (PortHandle > 0) then
begin
GetCommState(PortHandle,DCB);
DCB.BaudRate := Baudrate;
SetCommState(PortHandle,DCB)
end;
end;
function TComPort.GetFlags : Integer;
var
temp : TDCB;
begin
if (PortHandle > 0) then
begin
GetCommState(PortHandle,temp);
result := temp.Flags;
end
else
result := -1;
end;
function TComport.GetStopBits : byte;
var
temp : TDCB;
begin
if (PortHandle > 0) then
begin
GetCommState(PortHandle,temp);
result := temp.StopBits;
end
else
result := 255;
end;
procedure TComport.SetStopBits(bits : byte);
begin
if (bits > 0) and (bits <= 2) then // Der gültige Eingabebereich wird festgelegt
begin
GetDCB;
DCB.StopBits := bits;
SetCommState (PortHandle,DCB);
end;
end;
function TComport.GetByteSize : byte;
var
temp : TDCB;
begin
GetCommState(PortHandle,temp);
result := temp.ByteSize;
end;
procedure TComport.SetByteSize(bytesize : byte);
begin
if bytesize in [1..8] then
begin
GetDCB;
DCB.ByteSize := bytesize;
SetCommState (PortHandle,DCB);
end;
end;
procedure TComport.BufferSize(Size : Integer); //Sende -und Empfangspuffer setzen
begin
SetupComm(PortHandle,Size,Size);
end;
function TComport.CharInTXBuffer : Cardinal; // Zeigt die aktuele Anzahl an Bytes im Sendepuffer an.
var
Comstat : _Comstat;
Errors : DWord;
begin
if windows.ClearCommError(PortHandle,Errors,@Comstat) then
result := Comstat.cbOutQue else result := 0;
end;
function TComport.CharInRXBuffer : Cardinal; // Zeigt die aktuelle Anzahl an Bytes im Sendepuffer an.
var
Comstat : _Comstat;
Errors : DWord;
begin
if windows.ClearCommError(PortHandle,Errors,@Comstat) then
result := Comstat.cbInQue else result := 0;
end;
procedure TComport.ClearBuffer; // Alle Puffer sofort leeren. Alle noch zu sendenden bzw zu empfangenden Zeichen gehen verloren!
begin
windows.PurgeComm(PortHandle,PURGE_TXCLEAR);
windows.PurgeComm(PortHandle,PURGE_RXCLEAR);
end;
procedure TComport.SENDBYTE (Dat: Integer); // Ein einzelnes Byte (binär codiert) senden
var BytesWritten: DWord;
begin
WriteFile(PortHandle,Dat,1,BytesWritten,NIL);
END;
function TComport.READBYTE(): Integer; // Einen einzelnes Byte (binär codiert) empfangen
var Dat: Byte;
BytesRead: DWORD;
begin
ReadFile(PortHandle,Dat,1,BytesRead,NIL);
if BytesRead = 1 then Result:=Dat else Result := -1;
end;
procedure TComport.SENDSTRING (Buffer: Pchar); // Einen Character senden.
var BytesWritten: DWord;
begin
WriteFile(PortHandle,Buffer^,Length(Buffer),BytesWritten,NIL);
END;
function TComport.READSTRING(): Pchar; // Einen Character empfangen
var Dat: Integer;
Data: STRING;
begin
Dat := 0;
while ((Dat > -1) and (Dat <> 13)) do begin
Dat := ReadByte();
if ((Dat > -1) and (Dat <> 13)) then Data := Data + Chr(Dat);
end;
result := pchar(Data);
end;
destructor TComport.Destroy;
begin
if PortHandle > 0 then
CloseCom;
inherited;
end;
procedure Tcomport.Timeouts (TOut : Integer); // Setzen der Sendetimeouts
var
Timeout : TCommTimeOuts;
begin
TimeOut.ReadIntervalTimeout := 1;
TimeOut.ReadTotalTimeoutMultiplier := 1;
TimeOut.ReadTotalTimeoutConstant := TOut;
TimeOut.WriteTotalTimeoutMultiplier := 10;
TimeOut.WriteTotalTimeoutConstant := TOut;
SetCommTImeouts(PortHandle,Timeout);
end;
procedure TComport.GetDCB;
begin
GetCommState(PortHandle,DCB);
end;
function TComport.SetFlags (Flag : Integer; Enable : Boolean) : boolean; // Setzt spezielle Einstellungen des Ports
begin
GetDCB;
if Enable then
DCB.Flags := DCB.Flags or Flag
else
DCB.Flags := DCB.Flags and (not Flag);
result := Boolean(SetCommState(PortHandle,DCB));
end;
function TComport.GetStatusReport : String;
var
Str : String;
begin
Str := 'Baudrate von COM1: ' + IntToStr(Baudrate);
//Str := Str + chr(13) + 'Parität von COM1: ' + parity[Parity];
Str := Str + chr(13) + 'Flags von COM1: ' + IntToStr(GetFlags);
Str := Str + chr(13) + 'Bits/Byte von COM1: ' + IntToStr(ByteSize);
//Str := Str + chr(13) + 'Stopbits von COM1: ' + stopbits[StopBits];
Str := Str + chr(13) + 'Zeichen im RX-Puffer: ' + IntToStr(CharInRXBuffer);
Str := Str + chr(13) + 'Zeichen im TX-Puffer: ' + IntToStr(CharInTXBuffer);
result := Str;
end;
end.