Beispiel 2: Erweiterte ADS-Funktionsbausteine

Die VB-Applikation sendet ein Array mit Integer-Werten zu einer SPS-Task. Die zuletzt gesendeten Werte werden einer Liste hinzugefügt und in der SPS in eine entsprechende Array-Variable kopiert. Die VB-Applikation benutzt einen WRITE-Request um die Daten zu senden. In der SPS wird der ADSWRITEIND-Funktionsbaustein benutzt um die Daten zu empfangen und ADSWRITERES-Funkstionbaustein um den WRITE-Request zu quittieren. Um mit der SPS-Task zu kommunizieren benutzt die VB-Applikation das ActiveX Control: AdsOcx.

Beispiel 2: 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 und Index-Offset Parameter verschlüsselt. Z.B.:

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

Option Explicit
    
Dim AdsResult     As Integer
Dim arrData(0 To 9)   As Integer

Private Sub cmdWrite_Click()
    Call List1.Clear
    
    Dim i As Long
    For i = LBound(arrData) To UBound(arrData)
    arrData(i) = arrData(i) + 1 'change values
    Call List1.AddItem("arrData(" & i & ") = " & arrData(i))
    Next i
    
    'calculate the byte length parameter
    Dim cbWriteSize As Long
    cbWriteSize = (UBound(arrData) - LBound(arrData) + 1) * LenB(arrData(LBound(arrData)))
    
    AdsResult = AdsOcx1.AdsSyncWriteReq(&H80000005, &H7, cbWriteSize, arrData) 'send data to PLC
    Label1.Caption = "Ads result: " & AdsResult
    
End Sub

Private Sub Form_Load()
    AdsOcx1.AdsAmsServerNetId = AdsOcx1.AdsAmsClientNetId
    AdsOcx1.AdsAmsServerPort = 802 'PLC task number'
    
    Dim i As Long
    For i = LBound(arrData) To UBound(arrData)
    arrData(i) = i    'init data
    Next i
End Sub

Das SPS Programm

Die Requests werden in der SPS-Task von einer Instanz des ADSWRITEIND-Funktionsbausteins als Indications abgefangen. Danach werden die Parameter Index-Group, Index-Offset und die gesendete Datenlänge auf Gültigkeit überprüft und die gewünschte Operation an der SPS-Variablen durchgeführt. Als Nächstes wird ein Response von einer Instanz des ADSWRITERES-Funktionsbausteins an den Aufrufer (eventuell mit einem Fehlercode) zurückgesendet. Zum Schluss werden die Flags CLEAR und RESPOND rückgesetzt um weitere Indications verarbeiten zu können.

Beispiel 2: Erweiterte ADS-Funktionsbausteine 2:

Mit der steigenden Flanke am CLEAR-Eingang des ADSWRITEIND-Funktionsbausteins wird der Adresspointer auf die zuletzt gesendeten Daten ungültig ( == NULL ). Aus diesem Grund werden die gesendeten Daten zuerst in die SPS-Variable kopiert und dann der CLEAR-Eingang auf TRUE gesetzt.

 

PROGRAM MAIN
VAR
    fbWriteInd  : ADSWRITEIND;
    fbWriteRes  : ADSWRITERES;

    sNetId      : T_AmsNetID;
    nPort       : T_AmsPort;
    nInvokeId   : UDINT;
    nIdxGrp     : UDINT;
    nIdxOffs    : UDINT;
    cbWrite     : UDINT;(* Byte size of written data *)
    pWrite      : POINTER TO BYTE;(* Pointer to written data buffer *)
    nResult     : UDINT;(* Write indication result error code *)

    arrInt      : ARRAY[0..9] OF INT;(* Server data *)
END_VAR

 

fbWriteRes( RESPOND := FALSE );(* Reset response function block *)
fbWriteInd( CLEAR := FALSE );(* Trigger indication function block *)
IF ( fbWriteInd.VALID ) THEN
    
    sNetId      := fbWriteInd.NETID;
    nPort       := fbWriteInd.PORT;
    nInvokeId   := fbWriteInd.INVOKEID;
    nIdxGrp     := fbWriteInd.IDXGRP;
    nIdxOffs    := fbWriteInd.IDXOFFS;

    cbWrite     := fbWriteInd.LENGTH;
    pWrite      := fbWriteInd.DATAADDR;     
    nResult     := 16#701;(* ADS error: Service not supported by server *)

    CASE nIdxGrp OF
        16#80000005:
            CASE nIdxOffs OF
                16#00000007:
                    IF  cbWrite <= SIZEOF( arrInt ) THEN
                        MEMCPY( ADR( arrInt ), pWrite, MIN( cbWrite, SIZEOF(arrInt) ) );
                        nResult := 0;
                    ELSE(* ADS error (example): Invalid size *)
                        nResult := 16#705;
                    END_IF
            ELSE(* ADS error (example): Invalid index offset *)
                nResult := 16#703;
            END_CASE
    ELSE(* ADS error (example): Invalid index group *)
        nResult := 16#702;
    END_CASE

    fbWriteRes( NETID := sNetId,
                PORT := nPort,
                INVOKEID := nInvokeId,
                RESULT := nResult,
                RESPOND :=  TRUE ); (* Send write response *)

    fbWriteInd( CLEAR := TRUE ); (* Clear indication entry *)
END_IF

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