Synchroner Zugriff auf die SPS-Variablen
Voraussetzungen:
- Delphi 5.0 oder höher;
- TcAdsDLL.DLL;
- TcAdsDEF.pas und TcAdsAPI.pas, enthalten in der Datei delphi_adsdll_api_units.zip, falls Sie den Quelltext selbst übersetzen möchten;
Aufgabenstellung
Aus der Windows-Applikation soll synchron schreibend und lesend auf eine SPS-Variable zugegriffen werden. Die Variable ist vom Typ Integer (16 Bit) und liegt auf dem Offset 520 in dem Merkerbereich des ersten Laufzeitsystems der SPS.
Das SPS-Programm
Die SPS-Variable wird beim Start der SPS mit dem Wert 7 initialisiert.
PROGRAM MAIN
VAR
VARINT16 AT%MB520 :INT:=7;
END_VAR
Delphi 5 Programm
Die Deklarationen der benutzten TcAdsDLL-Funktionen befinden sich in den Pascal-Units TcAdsDEF.pas und TcAdsAPI.pas. Diese wurden über eine Uses-Klausel in das Projekt eingebunden.
unit DelphiAdsDLLSample1Unit;
interface
uses
TcAdsDEF, TcAdsAPI, Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, ComCtrls;
Die Beispielapplikation
In der Event-Funktion FormCreate wird die DLL-Funktion AdsPortOpenaufgerufen. Beim Erfolg liefert diese Funktion die geöffnete Portnummer, sonst eine Null. Eventuelle Fehler werden über eine Message-Box an den Benutzer ausgegeben. Beim Beenden der Anwendung muß der Port wieder geschlossen werden. In der Event-Funktion FormDestroy wird dabei die DLL-Funktion AdsPortCloseaufgerufen.
Wurde der Ads-Port erfolgreich geöffnet, dann wird eine weitere DLL-Funktion aufgerufen: AdsGetLocalAddress. Diese liefert die AMS-Addresse des lokalen TwinCAT-PC's zurück. Die AMS-Adresse wird für Schreib/Lese-Zugriffe auf die SPS-Variablen benötigt.
var
Form1 : TForm1;
ClientPort : longint;
LocalAddr : TAmsAddr;
IndexGroup : Integer;
IndexOffset : Integer;
varHandle : Integer;
Result : longint;
varValue : Smallint;
const varName: AnsiString = 'MAIN.VARINT16'; //Symbol name
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
ClientPort:= AdsPortOpen();
if ClientPort > 0 then {OK}
begin
Result:=AdsGetLocalAddress( @LocalAddr );
if Result = 0 Then {OK}
begin
AdsState.Panels.Items[5].Text:= Format('%d.%d.%d.%d.%d.%d',[
LocalAddr.netId.b[0], LocalAddr.netId.b[1], LocalAddr.netId.b[2],
LocalAddr.netId.b[3], LocalAddr.netId.b[4], LocalAddr.netId.b[5]]);
AdsState.Panels.Items[1].Text:=IntToStr( ClientPort );
LocalAddr.port := 801; //Set the Ads port number for read/write/readwrite
IndexGroup := $00004020; {memory range}
IndexOffset := 520; {byte offset of the PLC variable}
end
else {error}
begin
AdsState.Panels.Items[3].Text:=IntToStr( Result );
MessageBox(NULL,'AdsGetLocalAddress()', 'Error!', MB_OK)
end;
end
else {error}
MessageBox( NULL,'AdsPortOpen()', 'Error!', MB_OK );
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
AdsPortClose();
end;
Bei der Betätigung des Buttons AdsSyncRead, wird der Wert der SPS-Variablen synchron über deren lokierte Adresse ausgelesen und auf der Form ausgegeben. Dabei wird in der Event-Funktion OnSyncReadButtonClick die DLL-Funktion AdsSyncReadReq aufgerufen. Die Parameter IndexGroup, IndexOffset sind als globale Variablen definiert. Deren Werte werden beim Start der Applikation entsprechend gesetzt.
procedure TForm1.OnSyncReadButtonClick(Sender:
TObject);
begin
Result := AdsSyncReadReq( @LocalAddr,
IndexGroup, IndexOffset, sizeof(varValue), @varValue );
ReadLabel.Caption := Format( 'Result:
%d, Value: %d', [Result, varValue]);
end;
Ein Schreib-Zugriff auf die Variable wurde auf ähnliche Weise implementiert. In der Event-Funktion OnSyncWriteButtonClick wird die DLL-Funktion AdsSyncWriteReq aufgerufen und der Wert der SPS-Variablen =200 gesetzt.
procedure
TForm1.OnSyncWriteButtonClick(Sender: TObject);
begin
varValue := 200;
Result := AdsSyncWriteReq( @LocalAddr,
IndexGroup, IndexOffset, sizeof(varValue), @varValue );
WriteLabel.Caption := Format( 'Result:
%d', [Result]);
end;
Ein gleichzeitiger Lese- und Schreib-Zugriff auf SPS-Variablen kann über die DLL-Funktion AdsSyncReadWriteReq realisiert werden. In dem Beispiel wird der Wert der Variablen über ein Handle gelesen. Dabei wird über die AdsSyncReadWriteReq-Funktion das Handle der Variablen zuerst angefordert. Mit diesem Handle kann dann der Wert der Variablen über die Funktion AdsSyncReadReq gelesen werden. Das Handle muß dann über die Funktion AdsSyncWriteReq frei gegeben werden.
procedure
TForm1.OnGetValueByHandleClick(Sender: TObject);
begin
{get handle}
Result := AdsSyncReadWriteReq( @LocalAddr,
ADSIGRP_SYM_HNDBYNAME, 0, sizeof(varHandle), @varHandle,
Length(varName) + 1, @varName[1] );
GetHandleLabel.Caption := Format('Get
handle result: %d, Handle: 0x%x', [Result, varHandle] );
{get value}
Result := AdsSyncReadReq( @LocalAddr,
ADSIGRP_SYM_VALBYHND, varHandle, sizeof(varValue), @varValue
);
GetValueLabel.Caption := Format( 'Get
value result: %d, Value: %d', [Result, varValue] );
{release handle}
Result := AdsSyncWriteReq( @LocalAddr,
ADSIGRP_RELEASE_SYMHND, 0, sizeof(varHandle), @varHandle );
ReleaseHandleLabel.Caption := Format(
'Release handle result: %d', [Result] );
end;
Sollen die Werte mehrerer SPS-Variablen öfter asynchron gelesen werden, dann können die benötigten Handles in der Event-Funktion FormCreate beim Start der Applikation angefordert werden. Erst beim Beenden der Applikation in der Event-Funktion FormDestroy können sie wieder frei gegeben werden.
Sprache / IDE | Beispielprogram auspacken |
---|---|
Delphi XE2 | |
Delphi 5 oder höher (classic) |