Beispiel 1: Erweiterte ADS-Funktionsbausteine

In der Beispielapplikation werden von einer VB-Applikation READ-Requests an die SPS-Task gesendet um eine SPS-Zählervariable zu inkrementieren/dekrementieren oder zurücksetzen. Beim Erfolg wird der Wert der Zählervariablen an die VB-Applikation zurück gesendet und auf der Form Ausgegeben. Um mit der SPS-Task zu kommunizieren benutzt die VB-Applikation das ActiveX Control: AdsOcx.

Beispiel 1: Erweiterte ADS-Funktionsbausteine 1:

Hier können Sie die kompletten Sourcen zu der Beispielapplikation entpacken: Beispielapplikation mit den erweiterten ADS-Funktionsbausteinen

Die VB-Applikation

In der Form_Load-Routine wird eine Verbindung zu der SPS-Task aufgebaut ( Port 802 auf dem lokalen Rechner ). Der gewünschte Dienst in der SPS-Task wird in dem Index-Group-Parameter verschlüsselt:

Damit die Requests an die SPS-Task weiter geleitet werden, muss in dem Index-Group-Parameter das höchstwertige Bit gesetzt werden. Der Index-Offset-Parameter ist Null.

Option Explicit
    
Dim tmpData(1) As Integer
Dim AdsResult    As Integer

Private Sub Command1_Click()
    
    AdsResult = AdsOcx1.AdsSyncReadReq(&H80000001, &H0, 2, tmpData)
    Label1.Caption = "Ads result:" & AdsResult & " PLC data:" & tmpData(0)
    
End Sub

Private Sub Command2_Click()
    AdsResult = AdsOcx1.AdsSyncReadReq(&H80000002, &H0, 2, tmpData)
    Label1.Caption = "Ads result:" & AdsResult & " PLC data:" & tmpData(0)

End Sub

Private Sub Command3_Click()
    AdsResult = AdsOcx1.AdsSyncReadReq(&H80000003, &H0, 2, tmpData)
    Label1.Caption = "Ads result:" & AdsResult & " PLC data:" & tmpData(0)

End Sub

Private Sub Form_Load()
    AdsOcx1.AdsAmsServerNetId = AdsOcx1.AdsAmsClientNetId
    AdsOcx1.AdsAmsServerPort = 802 'PLC task number'
End Sub

Das SPS Programm

Die Requests werden in der SPS-Task von einer Instanz des ADSREADIND-Funktionsbausteins als Indications abgefangen. Danach werden die Parameter Index-Group, Index-Offset und die angeforderte Datenlänge auf Gültigkeit überprüft. In der CASE-Anweisung wird die gewünschte Operation an der SPS-Variablen durchgeführt. Beim Erfolg wird ein Response von einer Instanz des ADSREADRES-Funktionsbausteins an den Aufrufer mit dem aktuellen Wert der SPS-Variablen zurückgesendet. Im Fehlerfall eine entsprechende Fehlermeldung. Zum Schluss werden die Flags CLEAR und RESPOND rückgesetzt um weitere Indications verarbeiten zu können.

PROGRAM MAIN
VAR
    fbReadInd       : ADSREADIND;(* Indication function block instance *)
    fbReadRes       : ADSREADRES;(* Response function block instance *)

    sNetId      : T_AmsNetID;
    nPort       : T_AmsPort;
    nInvokeId       : UDINT;
    nIdxGrp     : UDINT;
    nIdxOffs        : UDINT;
    cbLength        : UDINT;(* Requested read data/buffer byte size *)
    
    cbRead      : UDINT;(* Returned read data/buffer byte size *)
    pRead       : POINTER TO BYTE;(* Pointer to returned read data/buffer *)
    nErrID      : UDINT;(* Read indication result error code *)
    
    nCounter        : INT;(* Server data *)
END_VAR

 

fbReadRes( RESPOND := FALSE );(* Reset response function block *)
fbReadInd( CLEAR := FALSE );(* Trigger indication function block *)
IF fbReadInd.VALID THEN(* Check for new indication *)

    sNetID := fbReadInd.NETID;
    nPort := fbReadInd.PORT;
    nInvokeID := fbReadInd.INVOKEID;
    nIdxGrp := fbReadInd.IDXGRP;
    nIdxOffs := fbReadInd.IDXOFFS;
    cbLength := fbReadInd.LENGTH;

    cbRead := 0;
    pRead := 0;
    nErrID  := 16#701;(* ADS error: Service not supported by server *)

    
    CASE nIdxGrp OF
        (*------------------------------------------------------------------------------------*)
        16#80000001:
            CASE nIdxOffs OF
                0:(* Increment counter value *)
                    IF cbLength >= SIZEOF(nCounter) THEN
                        nCounter := nCounter + 1;
                        cbRead := SIZEOF(nCounter);
                        pRead := ADR(nCounter);
                        nErrID := 0;
                    ELSE (* ADS error (example): Invalid size *)
                        nErrID := 16#705;
                    END_IF
            ELSE (* ADS error (example): Invalid index offset *)
                nErrID := 16#703;
            END_CASE
        (*------------------------------------------------------------------------------------*)
        16#80000002:
            CASE nIdxOffs OF
                0:(* Decrement counter value *)
                    IF cbLength >= SIZEOF(nCounter) THEN
                        nCounter := nCounter - 1;
                        cbRead := SIZEOF(nCounter);
                        pRead := ADR(nCounter);
                        nErrID := 0;
                    ELSE(* ADS error (example): Invalid size *)
                        nErrID := 16#705;
                    END_IF
            ELSE (* ADS error (example): Invalid index offset *)
                nErrID := 16#703;
            END_CASE
        (*------------------------------------------------------------------------------------*)
        16#80000003:
            CASE nIdxOffs OF
                0:(* Reset counter value *)
                    IF cbLength >= SIZEOF(nCounter) THEN
                        nCounter := 0;
                        cbRead := SIZEOF(nCounter);
                        pRead := ADR(nCounter);
                        nErrID := 0;
                    ELSE(* ADS error (example): Invalid size *)
                        nErrID := 16#705;
                    END_IF
            ELSE (* ADS error (example): Service is not supported by server *)
                nErrID := 16#701;(* ADS error: Service not supported *)
            END_CASE

    ELSE (* ADS error (example): Invalid index group *)
        nErrID := 16#702;
    END_CASE
    
    fbReadRes(      NETID := sNetID, 
                PORT := nPort, 
                INVOKEID := nInvokeID,
                LEN := cbRead, 
                DATAADDR := pRead,
                RESULT := nErrID, 
                RESPOND := TRUE );(* Send read response *)
                
    fbReadInd( CLEAR := TRUE ); (* Clear indication entry *)
END_IF

Hier können Sie die kompletten Sourcen zu der Beispielapplikation entpacken: Beispielapplikation mit den erweiterten ADS-Funktionsbausteinen