Step 7 ANY_Pointer und DB_Pointer

sophie

Level-1
Beiträge
2
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
ich möchte die Anzahl der Werte von der Startadresse des ANY-Pointers (P#DB10.DBX 4.0 INT 5) auf die Zieladresse des DB-Pointers (DB13.DBX2.0)übertagen, die in dem ANY-Pointer stehen.
Folgende steht meine Lösung, ich weiß nicht, ob das richtig ist.

L P##Startadresse
LAR1
L P##Zieladresse
LAR2

L W [AR1,P#2.0]
T W [AR2,P#2.0]
L W [AR2,P#2.0]
T #Anzahl_DB
 
Hallo,

auch heute wieder der Hinweis: schau Dir den Aufbau der Datentypen POINTER und ANY in der Step7 Hilfe an.
Tipp fürs Anfangen: im Simatic Manager klicke im Menü auf
- Hilfe > Hilfethemen > Index > Pointerformat > Format des Parametertyps POINTER
- Hilfe > Hilfethemen > Index > ANY > Format des Parametertyps ANY

Du mußt die Einzelangaben
- Quell-DB
- Quell-Adresse
- Anzahl und Typ der Werte
- Ziel-DB
- Ziel-Adresse
aus den Pointern extrahieren.

Du mußt vor dem Kopieren beide DB öffnen. ("AUF DB [#QuellDB]" + "AUF DI [#ZielDB]")
Damit die L/T-Operationen wissen auf welchen DB sie sich beziehen sollen, muß ein DB als Global-DB (DB) und ein DB als Instanz-DB (DI) geöffnet werden. Die L- und T-Operationen müssen angeben, auf welchen offenen DB sie sich beziehen ("L DBW [AR1, ...]" + "T DIW [AR2, ...]")
Dann mußt Du die im Quell-ANY angebene Anzahl INT-Werte (entspricht Speichergröße WORD) (oder eventuell anderer Typ?) kopieren; in Deinem Adressbeispiel also 5 mal "L DBW ..." + "T DIW ..."

Soll der Code in einer Function (FC) oder in einem Function_Block (FB) programmiert werden?
Soll Dein Code allgemein gehalten sein, z.B. mit Schleife für die Anzahl zu übertragender Werte oder sind es immer 5 INT? Sind es immer INT oder können es auch BYTE oder DWORD sein?
Oder soll der Code nur für genau die angegebenen Adressen "P#DB10.DBX 4.0 INT 5" --> "P#DB13.DBX2.0" funktionieren?
Die SFC20 BLKMOV darfst Du vermutlich nicht benutzen?

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Tipp: so zerlegst Du bei einer Function (FC) den Input-ANY:
Code:
      L     P##IN_Startadresse_Any      //Adresse des IN-Parameters im Aufrufer-L-Stack
      LAR1  

      L     B [AR1,P#0.0]               //Prüfen ANY:S7-ANY-Kennung muß 16#10 sein!
      L     B#16#10
      <>I   
      SPB   err                         //Fehler: Aktualoperand ist kein ANY!

      L     B [AR1,P#1.0]               //ANY:Datentyp, z.B. 16#05 für INT 
      T     #Typ                        // (TEMP, Int)
      L     W [AR1,P#2.0]               //ANY:Wiederholfaktor
      T     #Anzahl                     // (TEMP, Int)
      L     W [AR1,P#4.0]               //ANY:DB-Nummer
      T     #QuellDB                    // (TEMP, Word)
      L     D [AR1,P#6.0]               //ANY:Bereichsadresse mit Bereichskennung, muß auf .0 enden!
      T     #QuellAdr                   // (TEMP, DWord)

Die Bereichsadresse muß (außer bei Datentyp BOOL) auf .0 enden, d.h. die niedrigsten 3 Bits (Bitadresse) müssen 0 sein.

Harald
 
Du solltest zudem beachten, dass das System das AR2 verwendet, dadurch muss bei Verwendung des AR2 in FB einiges beachtet werden. Hierzu die STEP7 Hilfe zum Thema Adressregister beachten.
 
Hallo PN/DP,

ich habe Deine "Zerlegung" mal als Vorlage genommen. Ich rufe den FC z.B. mit p#DB11.DBX22. DINT 33 als IN-Parameter auf.
Im FC möchte ich nun die 33 DINTs mit Loop aufsummieren. Dabei brech ich mir gerade die Füße. Hast Du da einen Tip für mich?

Gruß HaKa
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo, das sollte ungefähr so funktionieren:
Code:
//*** ANY des übergebenen Bereichs zerlegen und prüfen
      L     P##IN_Startadresse_Any      //Adresse des IN-Parameters im Aufrufer-L-Stack
      LAR1  

      L     B [AR1,P#0.0]               //Prüfen ANY:S7-ANY-Kennung muß 16#10 sein!
      L     B#16#10
      <>I   
      SPB   err                         //Fehler: Aktualoperand ist kein ANY!

      L     B [AR1,P#1.0]               //ANY:Typ 
      L     B#16#7                      //ANY:Typ 16#07 DINT
      <>I   
      SPB   err                         //Fehler: Aktualoperand zeigt nicht auf DINT-Array!

      L     W [AR1,P#2.0]               //ANY:Wiederholfaktor
      T     #Anzahl                     //Anzahl DINTs

      L     W [AR1,P#4.0]               //ANY:DB-Nummer
      T     #QuellDB
      L     D [AR1,P#6.0]               //ANY:Bereichsadresse mit Bereichskennung, muß auf .0 enden!
      T     #QuellAdr

//*** Summe über übergebenen Bereich bilden
      L     0
      T     #diSumme                    //Summe initialisieren (TEMP, DInt)
      LAR1  #QuellAdr                   //AR1 auf ersten DINT des übergebenen Bereichs setzen
      AUF   DB [#QuellDB]               //DB des übergebenen Bereichs öffnen

      L     #Anzahl                     //( FOR i := #Anzahl TO 0 BY -1 DO )
loop: T     #i                          //Schleifenzähler

      L     D [AR1,P#0.0]               //Wert des DINT aus Quell-Bereich lesen
      L     #diSumme                    //auf Zwischensumme
      +D                                //aufaddieren
      T     #diSumme

      +AR1  P#4.0                       //Pointer auf nächsten DINT weiterstellen (4 Bytes weiter)
      L     #i                          //Schleifenzähler
      LOOP  loop                        //--i und fertig? oder nächster Schleifendurchlauf

      L     #diSumme                    //Gesamtsumme
      T     #RET_VAL                    //als Funktionswert zurückgeben

      BE                                //RETURN 

err:  SET                               //noch Fehlerbehandlung...

Harald
 
Zurück
Oben