Meine Klasse Kommunikation hat folgende Methode:
Delphi-Quellcode:
function TKommunikation.Communicate(Order:TOrder; Adresse:TAdress;var Data:TDaten):Integer;
{ ************************* Kommunikationsmodul ************************** }
var
Opened:integer; // Variable die den Zustand der Verbindung zeigt
{*** Zählervariablen: **}
iPolling : integer; // Variable zum Pollen der Schnittstelle
iData : integer; // Variable für den Abbruch, falls die Daten falsch sind
iTimeout : integer; // Variable für den TimeOut
QBytes : integer; // Anzahl der Bytes am Port
varcheckchecksum: integer;
varcheckcommand : integer;
varcheckAdressH : integer;
varcheckAdressL : integer;
varcheckData1 : integer;
varcheckData2 : integer;
varcheckData3 : integer;
varcheckData4 : integer;
dataOk : boolean;
i : integer;
res : DWord;
tick : DWORD;
TimeOut : DWORD;
MilliSeconds : DWORD;
_time: DWORD;
_time1: DWORD;
time1: Cardinal;
time2: Cardinal;
Begin
// fCS.Enter; { Wechselseitger Ausschluss }
//fCS.TryEnter;
// _time:= GetTickCount;
if NOT(Assigned(Schnittstelle)) then
begin
result:=300;
exit;
end;
if NOT(Schnittstelle.isConnected) then
begin
Result:=111;
exit;
end;
dataOk:=true;
varcheckcommand:=0;
varcheckAdressH:=0;
varcheckAdressL:=0;
varcheckData1:=0;
varcheckData2:=0;
varcheckData3:=0;
varcheckData4:=0;
varcheckchecksum:=0;
QBytes:=0;
Opened:=0;
iData:=1;
iTimeOut:=0; // Timeout Variable wird mit 0 initialisiert
// Schnittstelle.FlushBufferIN; {Schnittstellenpuffer löschen}
// Schnittstelle.FlushBufferOut; {Schnittstellenpuffer löschen}
//****************** Befehl wird gesetzt***********************//
//Befehl zB.: ReadWord (RW) oder (WR) WriteRequest oder (RF) ReadFloat
case Order of
READ_WORD: ReadWord(Adresse.RS485Adress,Adresse.AdressHigh,Adresse.AdressLow);
READ_BYTE: ReadByte(Adresse.RS485Adress,Adresse.AdressHigh,Adresse.AdressLow);
// READ_FLOAT: ReadFloat(Adresse.RS485Adress,Adresse.AdressHigh,Adresse.AdressLow);
WRITE_WORD: WriteWord(Adresse.RS485Adress,Adresse.AdressHigh,Adresse.AdressLow,Data.Data1,Data.Data2);
WRITE_BYTE: WriteByte(Adresse.RS485Adress,Adresse.AdressHigh,Adresse.AdressLow,Data.Data2);
// WRITE_FLOAT: WriteFloat(Adresse.RS485Adress,Adresse.AdressHigh,Adresse.AdressLow,Data.Data1,Data.Data2,Data.Data3,Data.Data4);
// WRITE_RESET: WriteReset(Adresse.RS485Adress);
WRITE_REQUEST: WriteRequest(Adresse.RS485Adress);
end;
// ***********************************************************//
repeat
if Schnittstelle.GetQBytes >0 then
begin
Schnittstelle.FlushBufferIN; {Schnittstellen[eingangs]puffer löschen}
end;
Schnittstelle.SendBytes(7,fBufferOut); {Ausgangspuffer senden}
iPolling:=1;
repeat
QBytes:=Schnittstelle.GetQBytes; // Bytes am Port
Sleep(SLEEP_POLL_TIME); ////////////////////////////////// HIER wird gepolllt
inc(iPolling);
until ((QBytes =7) Or (iPolling >I_POLLING_MAX));
if (QBytes=7) then
begin
Schnittstelle.ReceiveBytes(7,fBufferIn); {Schnittstelleneingang lesen}
Result:=0;
dataOk:=false;
//*********** DATENÜBERPRÜFUNG************
varcheckchecksum := Checkchecksum;
varcheckcommand := CheckCommand;
varcheckAdressH := CheckAdressH;
varcheckAdressL := checkAdressL;
//******************************************
// Bei Schreibbefehlen muss der komplette Frame, der gesendet wurde
// auch wieder zurückkommen
if ((Order=WRITE_REQUEST)Or
(Order=WRITE_RESET)Or
(Order=WRITE_BYTE)Or
(Order=WRITE_WORD)Or
(Order=WRITE_FLOAT)) then
begin
if ((varcheckchecksum=0)
and (varcheckcommand=0)
and (varcheckAdressH=0)and (varcheckAdressL=0)) then
begin
dataOk:=true;
inc(fCounts);
result:=comOK; // Kommunikation i.O.
if Assigned(fOnNewCount) then fOnNewCount(fCounts);
exit
end;
end
else
begin
// Bei den Lesebefehlen muss die Checksum + AdresseHigh+ AdresseLow stimmen
If ((varcheckchecksum=0) and (varcheckcommand=0) and (varcheckAdressH=0) and (varcheckAdressL=0)) then
begin
dataOk:=true;
result:=comOK; // Kommunikation i.O.
// _time1:= GetTickCount - _time;
// fDateiListe.Add('Polling:= '+IntToStr(iPolling));
// fDateiListe.Add('Time:= '+IntToStr(_time1));
// fDateiListe.SaveToFile('C:\Logdatei.txt');
// ShowMessage( IntToHex (fbufferIn[1],2) +' '+ IntToStr(_time1));
Data.Data1 := fBufferIn[4];
Data.Data2 := fBufferIn[5];
Data.Data3 := fBufferIn[6];
Data.Data4 := fBufferIn[7];
inc(fCounts);
// if Assigned(fOnNewCount) then begin fOnNewCount(fCounts); end;
exit;
end;
end;
end;
inc(iTimeout);
until (iTimeout>=TIME_OUT_WAIT_COUNTS) Or (dataOk=False) ;
if (iTimeout>=TIME_OUT_WAIT_COUNTS) then
begin
Result:=comTimeOut; // TimeOut verursacht
if Assigned(OnTimeOut) then
begin
fOnTimeOut(Self);
end;
// MessageDlg('TimeOut', mtError, [mbOk], 0); { TODO : TimeOut MessagDlg muss noch entfernt werden }
// Schnittstelle.Disconnect;
exit;
end
else
begin
Result:=comBadData; // Fehler bei den angekommenen Daten
// MessageDlg('Fehler bei den angekommenen Daten', mtError, [mbOk], 0);{ TODO : BadData MessagDlg muss noch entfernt werden }
fCS.Leave;
end;
End;
Es gibt folgenden ablauf:
1.Senden
2.Warten
3.Überprüfen ob 7 Bytes da sind
--> JA dann 7 Bytes lesen und auf Gültigkeit prüfen
--> Nein Counter hochzählen weiter mit 3
wenn Counter > x
dann nochmal 1 und counter2 hochzählen (also nochmal senden)
irgendwann muss abgebrochen werden (nach dem 3. mal Senden beispielsweise..)
Gruß