Hi, this my example program for comm. pc and plc. system speaking over the DM area sorry my english still terrible because of this i cant write more english comment its only for education,, this picture show dm write package this is my example system i used Cport v3.0, LMDTools v6.11, Delphi 7 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, CPort, StdCtrls, ExtCtrls, CPortCtl, LMDCustomComponent, LMDWndProcComponent, LMDCustomFormFill, LMDFormFill, Buttons, LMDControl, LMDBaseControl, LMDBaseGraphicControl, LMDBaseLabel, LMDCustomSimpleLabel, LMDSimpleLabel, LMDGraphicControl, LMDBaseMeter, LMDCustomProgressFill, LMDProgressFill, LMDBaseShape, LMDShapeControl, LMDShadowFill, LMDLEDCustomLabel, LMDLEDLabel, LMDScrollText; type TForm1 = class(TForm) ComPort1: TComPort; TimerPLCRead: TTimer; Panel1: TPanel; ComLed1: TComLed; ComLed2: TComLed; ComLed3: TComLed; Label1: TLabel; Label2: TLabel; Label3: TLabel; LMDFormFill1: TLMDFormFill; BitBtn1: TBitBtn; Memo2: TMemo; Image1: TImage; Image2: TImage; Image3: TImage; LMDSimpleLabel1: TLMDSimpleLabel; LMDSimpleLabel2: TLMDSimpleLabel; LMDProgressFill1: TLMDProgressFill; SpeedButton1: TSpeedButton; SpeedButton2: TSpeedButton; LMDShapeControl1: TLMDShapeControl; Image4: TImage; Image5: TImage; LMDSimpleLabel3: TLMDSimpleLabel; LMDSimpleLabel4: TLMDSimpleLabel; SpeedButton3: TSpeedButton; SpeedButton4: TSpeedButton; LMDShapeControl2: TLMDShapeControl; LMDSimpleLabel5: TLMDSimpleLabel; LMDLEDLabel1: TLMDLEDLabel; LMDSimpleLabel6: TLMDSimpleLabel; LMDLEDLabel2: TLMDLEDLabel; LMDSimpleLabel7: TLMDSimpleLabel; LMDShadowFill1: TLMDShadowFill; LMDSimpleLabel8: TLMDSimpleLabel; Image6: TImage; Image7: TImage; Image8: TImage; LMDSimpleLabel9: TLMDSimpleLabel; LMDSimpleLabel10: TLMDSimpleLabel; LMDProgressFill2: TLMDProgressFill; SpeedButton5: TSpeedButton; SpeedButton6: TSpeedButton; LMDShapeControl3: TLMDShapeControl; LMDLEDLabel3: TLMDLEDLabel; LMDSimpleLabel14: TLMDSimpleLabel; LMDLEDLabel4: TLMDLEDLabel; LMDSimpleLabel15: TLMDSimpleLabel; LMDShadowFill2: TLMDShadowFill; LMDSimpleLabel16: TLMDSimpleLabel; Image11: TImage; LMDSimpleLabel11: TLMDSimpleLabel; Image9: TImage; Image10: TImage; LMDSimpleLabel17: TLMDSimpleLabel; LMDSimpleLabel18: TLMDSimpleLabel; SpeedButton7: TSpeedButton; SpeedButton8: TSpeedButton; LMDShapeControl4: TLMDShapeControl; Image12: TImage; Image13: TImage; Image14: TImage; Label4: TLabel; Label5: TLabel; LMDSimpleLabel12: TLMDSimpleLabel; LMDSimpleLabel13: TLMDSimpleLabel; procedure FormCreate(Sender: TObject); procedure TimerPLCReadTimer(Sender: TObject); procedure BitBtn1Click(Sender: TObject); Function hexToInt(hexStr: string): longint; procedure VarstoEdits; procedure SpeedButton4Click(Sender: TObject); procedure Panel1Click(Sender: TObject); private cSendBuffer : PChar; // outgoing buffer cRcvBuffer : PChar; // incomming buffer CharCntReceived : Integer; // incomming charecter count iErrorCount : integer; // Error Count myReadOnlyDMArea : array [0..14] of Word; // PLC DM area procedure CalcCRC(sStr:PChar;iLength :Integer; var Fcs1,Fcs2:Char); Function CheckCRC(sStr:PChar;iLength :Integer): Boolean; { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} {--------------------------------------------------------------------------} procedure TForm1.FormCreate(Sender: TObject); var i:integer; begin cRcvBuffer := StrAlloc(512); cSendBuffer := StrAlloc(512); for i:=0 to 511 do cSendBuffer[i] := #0; for i:=0 to 14 do myReadOnlyDMArea[i]:=0; CharCntReceived := 0; iErrorCount := 3; comport1.Connected:=TRUE; comport1.ClearBuffer(TRUE,TRUE); TimerPLCRead.Enabled := TRUE; end; {--------------------------------------------------------------------------} {Tform1.FormClose} procedure TForm1.BitBtn1Click(Sender: TObject); begin // Program kapatılmadan önce timer ve seri port kapatılmalı. // Seri portta çıkan bir hatadan dolayı kapatmadan önce Clearbuffer ile temizlenmesi lazım TimerPLCRead.Enabled:=FALSE; comport1.ClearBuffer(TRUE,TRUE); //comport1.Connected:=FALSE; Close; end; {--------------------------------------------------------------------------} // Tüm SpeedButtonlar Bu Fonksiyna Bağlı (* DM 4: Valve and pomp output (100.00 .. ) 0001 : Output 100.0 Depot 2 - out valve and pomp 0010 : Output 100.1 Depot 2 - witer valve 0100 : Output 100.2 Depot 1 - Çıkış Valfi-Pompa 1000 : Output 100.3 Depot 1 - Giriş Valfi *) procedure TForm1.SpeedButton4Click(Sender: TObject); var cFcs1 , cFcs2:Char; begin try cSendBuffer[0] := '@'; cSendBuffer[1] := '0'; cSendBuffer[2] := '0'; cSendBuffer[3] := 'W'; cSendBuffer[4] := 'D'; cSendBuffer[5] := '0'; cSendBuffer[6] := '0'; cSendBuffer[7] := '0'; cSendBuffer[8] := '4'; if SpeedButton1.Down then cSendBuffer[9] := '1' else cSendBuffer[9] := '0'; if SpeedButton3.Down then cSendBuffer[10] := '1' else cSendBuffer[10] := '0'; if SpeedButton5.Down then cSendBuffer[11] := '1' else cSendBuffer[11] := '0'; if SpeedButton7.Down then cSendBuffer[12] := '1' else cSendBuffer[12] := '0'; CalcCRC(@cSendBuffer[0], 13, cFcs1, cFcs2); cSendBuffer[13] := cFcs1; cSendBuffer[14] := cFcs2; cSendBuffer[15] := '*'; cSendBuffer[16] := #13; cSendBuffer[17] := #0; label4.Caption:= cSendBuffer; comport1.WriteStr(cSendBuffer); iErrorCount:= 4; finally //TimerPLCRead.Enabled:=TRUE; end; end; {--------------------------------------------------------------------------} procedure TForm1.TimerPLCReadTimer(Sender: TObject); var PacketOK : boolean; LastCount : integer; y : integer; begin inc(iErrorCount); // Porttan tampona gelen veriyi alır ve tampon değişkene aktarır. // Eğer AsyncPro bileşenleri kullanılacak ise bu iki satır siline aşağıdaki ek yapıla LastCount := comport1.read(cRcvBuffer[CharCntReceived],512); CharCntReceived := CharCntReceived + LastCount; PacketOK := ((CharCntReceived = 71 ) and (cRcvBuffer[0] = '@') and (cRcvBuffer[69] = '*')); if PacketOK then PacketOK := CheckCRC(@cRcvBuffer[0],67); if PacketOK or (iErrorCount > 5 ) then begin //Eğer packet sağlam ise stringi parse et.. if PacketOK then begin for y:=0 to 14 do myReadOnlyDMArea[y] := hexToInt(Uppercase(copy(cRcvBuffer,8+(y*4),4))); VarsToEdits; end; // Bufferi temizle ve PLC'den yeni paket veri iste iErrorCount:=0; CharCntReceived := 0; comport1.WriteStr('@00RD0000001552*'+#13+#0); end; end; {--------------------------------------------------------------------------} (*<<<>>><<<>>>DM Area Map<<<>>><<<>>> DM 0 : Depo 1 Analog Sıcaklık Bilgisi DM 1 : Depo 1 Analog Basınç Bilgisi DM 2 : Depo 2 Analog Sıcaklık Bilgisi DM 3 : Depo 2 Analog Basınç Bilgisi <<<>>><<<>>>DM Area Map<<<>>><<<>>>*) procedure Tform1.VarstoEdits; var tempStr : string; y : integer; begin //<<<>>><<<>>>DEPO 1 için<<<>>><<<>>> //Sıcaklık tempStr:= Floattostrf(((myReadOnlyDMArea[0]*200/65535)-100),fffixed,8,1); while length(tempStr)<6 do tempStr:= ' '+tempStr; LMDLEDLabel1.Caption := tempStr+' C'; //Basınçtan miktar LMDProgressFill1.UserValue := myReadOnlyDMArea[1]; tempStr:= Floattostrf(((myReadOnlyDMArea[1]*4000/65535)),fffixed,8,1); while length(tempStr)<6 do tempStr:= ' '+tempStr; LMDLEDLabel2.Caption := tempStr+' L'; //<<<>>><<<>>>DEPO 2 için<<<>>><<<>>> //Sıcaklık tempStr:= Floattostrf(((myReadOnlyDMArea[2]*200/65535)-100),fffixed,8,1); while length(tempStr)<6 do tempStr:= ' '+tempStr; LMDLEDLabel3.Caption := tempStr+' C'; //Basınçtan miktar LMDProgressFill2.UserValue := myReadOnlyDMArea[3]; tempStr:= Floattostrf(((myReadOnlyDMArea[3]*4000/65535)),fffixed,8,1); while length(tempStr)<6 do tempStr:= ' '+tempStr; LMDLEDLabel4.Caption := tempStr+' L'; //Memo2 gelen DM bilgilerini ekranda göstermek için kullanılır. //Memo2 LED panele tıklayınca açılır. if memo2.Visible then begin memo2.Lines.Clear; for y:=0 to 14 do memo2.Lines.Add('DM'+inttostr(y)+' = ' + inttostr(myReadOnlyDMArea[y])); end; end; (* -------------------------------------------------------------------------- -------------------------- YARDIMCI FONKSIYONLAR ------------------------- -------------------------------------------------------------------------- HexToInt : girilen Hexadesimal sayıyı integera çevirir CalcCRC : girilem Length uzunluğunda pchar stringin 16bit CRC kodunu hesaplar ChechkCRC: girilen Length uzunluğunda pchar stringin 16bit CRC kodunu hesaplar ve verilen CRC kodu ile karşılaştırır, doğru ise TRUE döner. *) Function Tform1.hexToInt(hexStr: string): longint; var iErr:integer; begin Result := 0; Val('$' + hexStr,Result , iErr); end; {--------------------------------------------------------------------------} procedure TForm1.CalcCRC(sStr:PChar;iLength :Integer;var Fcs1,Fcs2:Char); var cFcs, cTmpFcs:Byte; i:Integer; begin cFcs := 0; for i := 0 to iLength-1 do cFcs := cFcs XOR ORD(sStr[i]); cTmpFcs := cFcs AND $0f; if cTmpFcs > $09 then Fcs2:=CHAR(cTmpFcs+$37) else Fcs2:=CHAR(cTmpFcs+$30); cTmpFcs := cFcs SHR 4; if cTmpFcs > $09 then Fcs1:=CHAR(cTmpFcs+$37) else Fcs1:=CHAR(cTmpFcs+$30); end; {--------------------------------------------------------------------------} Function TForm1.CheckCRC(sStr:PChar;iLength :Integer): Boolean; var cFcs1, cFcs2: Char; begin result:= FALSE; CalcCRC(@sStr[0], iLength, cFcs1, cFcs2); if (cFcs1 = sStr[67]) and (cFcs2 = sStr[68]) then Result := TRUE; end; {--------------------------------------------------------------------------} procedure TForm1.Panel1Click(Sender: TObject); begin //Memo2 gelen DM bilgilerini ekranda göstermek için kullanılır. //LED panele tıklayınca açılır. memo2.Visible := NOT memo2.Visible; label4.Visible := NOT label4.Visible; end; end. object ComPort1: TComPort BaudRate = br9600 Port = 'COM1' Parity.Bits = prEven StopBits = sbTwoStopBits DataBits = dbSeven Events = [evRxChar, evTxEmpty, evRxFlag, evRing, evBreak, evCTS, evDSR, evError, evRLSD, evRx80Full] FlowControl.OutCTSFlow = False FlowControl.OutDSRFlow = False FlowControl.ControlDTR = dtrDisable FlowControl.ControlRTS = rtsDisable FlowControl.XonXoffOut = False FlowControl.XonXoffIn = False Left = 112 Top = 16 end if you want to use Turbo power AsyncPro component, add on this form procedure TForm1.ApdComPort1TriggerAvail(CP: TObject; Count: Word); var LastCount,I : integer; begin LastCount:= Count; for I := 1 to LastCount do begin cRcvBuffer[CharCntReceived]:= ApdComPort1.GetChar; inc(CharCntReceived); end; end; and ApdComPort1.OutPut := '@00RD0000001552*'+#13+#0; //comport1.WriteStr('@00RD0000001552*'+#13+#0); and object ApdComPort1: TApdComPort ComNumber = 1 Baud = 9600 Parity = pEven DataBits = 7 StopBits = 2 TraceName = 'APRO.TRC' LogName = 'APRO.LOG' OnTriggerAvail = ApdComPort1TriggerAvail Left = 32 Top = 32 end i shared this example on turkish forum, and iwantto share it in here too,