S7 Indirekte Adressierung

Rommani

Level-1
Beiträge
53
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,
ich habe ein Problem und zwar möchte ich mit Indirekte Adressierung zahlen von 1 bis 100 in Datenbaustein DB10 schreiben

dh:
#Array[0]= 1
#Array[1]= 2
….
#Array[99]= 100

DATA_BLOCK DB 10
TITLE =
VERSION : 0.1
STRUCT
Werten : ARRAY [0 .. 99 ] OF REAL ;
END_STRUCT ;
BEGIN
Zum Einsatz kommt eine CPU 315
Ein paar Tipps sind willkommen. :wink:
MFG
 
tipp 1: 100 ist kein realwert
tipp 2: warum die werte aus nem array nehmen, einfacher ist doch selber "berechnen"

daraus ergibt sich tipp 3: nimm eine schleife, leg eine zählvariable an, inkrementiere sie in jedem schleifendurchlauf und shreib sie per

Code:
*
T      DBD [AR1,P#0.0]
tipp 4: erhöhe die adresse mit

Code:
*
+AR1     P#4.0
tipp 5: schau in die FAQ hier im forum zum thema pointer
 
Zuletzt bearbeitet:
Hallo vierlagig
vielen Dank für das schnelle Antworte, aber was meinst du mit "einfacher ist doch selber "berechnen" "

kannst du ma bitte genauer erklären bzw. ein Bsp.

nochmal danke
 
ich habe ein Problem und zwar möchte ich mit Indirekte Adressierung zahlen von 1 bis 100 in Datenbaustein DB10 schreiben

dh:
#Array[0]= 1
#Array[1]= 2
….
#Array[99]= 100

DATA_BLOCK DB 10
TITLE =
VERSION : 0.1
STRUCT
Werten : ARRAY [0 .. 99 ] OF REAL ;
END_STRUCT ;
BEGIN

Hier ist einmal ein kurzes Programmbeispiel für das Schreiben der Werte 1.0 bis 10.0 in einen Datenbaustein:

Code:
FUNCTION FC 100 : VOID
TITLE =Werte in DB schreiben
AUTHOR : KAI
FAMILY : SPSFORUM
NAME : WERTE
VERSION : 1.0
 
VAR_INPUT
  DB_WERTE : BLOCK_DB ; 
  ANZAHL_WERTE : INT ; 
  WERTE_SCHREIBEN : BOOL ; 
END_VAR
VAR_IN_OUT
  WERTE_SCHREIBEN_FLANKE : BOOL ; 
END_VAR
VAR_TEMP
  DB_REGISTER : WORD ; 
  AR1_REGISTER : DWORD ; 
  WERT : REAL ; 
  SCHLEIFE : INT ; 
END_VAR
BEGIN
NETWORK
TITLE =Werte in DB schreiben
 
      U     #WERTE_SCHREIBEN; // Werte schreiben
      FP    #WERTE_SCHREIBEN_FLANKE; // Werte schreiben Flanke
      NOT   ; 
      BEB   ; // Bausteinende
 
NETWORK
TITLE =Register sichern
 
      L     DBNO; // DB-Register
      T     #DB_REGISTER; 
 
      TAR1  #AR1_REGISTER; // AR1-Register
 
NETWORK
TITLE =Werte in DB schreiben
 
      AUF   #DB_WERTE; // DB-Werte
 
      L     1.000000e+000; 
      T     #WERT; // Wert
 
      L     P#0.0; 
      LAR1  ; 
 
      L     #ANZAHL_WERTE; // Anzahl Werte
M01:  T     #SCHLEIFE; 
 
      L     #WERT; // Wert
      T     DBD [AR1,P#0.0]; 
 
      L     #WERT; // Wert
      L     1.000000e+000; 
      +R    ; 
      T     #WERT; // Wert
 
      L     P#4.0; 
      +AR1  ; 
 
      L     #SCHLEIFE; 
      LOOP  M01; 
 
NETWORK
TITLE =Register wiederherstellen
 
      AUF   DB [#DB_REGISTER]; // DB-Register
 
      LAR1  #AR1_REGISTER; // AR1-Register
 
END_FUNCTION

Gruß Kai
 

Anhänge

  • OB1.pdf
    5,9 KB · Aufrufe: 78
  • FC100.pdf
    6,8 KB · Aufrufe: 94
  • DB100.pdf
    4,4 KB · Aufrufe: 74
  • Werte.zip
    32,6 KB · Aufrufe: 46
Zuviel Werbung?
-> Hier kostenlos registrieren
Nach Rücksprache mit Rommani hier noch einmal ein leicht geändertes Programmbeispiel:

Code:
FUNCTION FC 100 : VOID
TITLE =Werte in DB schreiben
AUTHOR : KAI
FAMILY : SPSFORUM
NAME : WERTE
VERSION : 1.0
 
VAR_INPUT
  ARRAY_WERTE : ARRAY  [0 .. 9] OF REAL ; 
  ANZAHL_WERTE : INT ; 
  WERTE_SCHREIBEN : BOOL ; 
END_VAR
VAR_IN_OUT
  WERTE_SCHREIBEN_FLANKE : BOOL ; 
END_VAR
VAR_TEMP
  DB_REGISTER : WORD ; 
  AR1_REGISTER : DWORD ; 
  DB_NUMMER : WORD ; 
  WERT : REAL ; 
  SCHLEIFE : INT ; 
END_VAR
BEGIN
NETWORK
TITLE =Werte in DB schreiben
 
      U     #WERTE_SCHREIBEN; // Werte schreiben
      FP    #WERTE_SCHREIBEN_FLANKE; // Werte schreiben Flanke
      NOT   ; 
      BEB   ; // Bausteinende
 
NETWORK
TITLE =Register sichern
 
      L     DBNO; // DB-Register
      T     #DB_REGISTER; 
 
      TAR1  #AR1_REGISTER; // AR1-Register
 
NETWORK
TITLE =Werte in DB schreiben
 
      L     P##ARRAY_WERTE; // Pointer
      LAR1  ; 
 
      L     W [AR1,P#0.0]; // DB-Nummer
      T     #DB_NUMMER; 
 
      AUF   DB [#DB_NUMMER]; 
 
      L     D [AR1,P#2.0]; // Bereichszeiger
      LAR1  ; 
 
      L     1.000000e+000; 
      T     #WERT; // Wert
 
      L     #ANZAHL_WERTE; // Anzahl Werte
M01:  T     #SCHLEIFE; 
 
      L     #WERT; // Wert speichern
      T     DBD [AR1,P#0.0]; 
 
      L     #WERT; // Wert erhöhen
      L     1.000000e+000; 
      +R    ; 
      T     #WERT; 
 
      L     P#4.0; 
      +AR1  ; 
 
      L     #SCHLEIFE; 
      LOOP  M01; 
 
NETWORK
TITLE =Register wiederherstellen
 
      AUF   DB [#DB_REGISTER]; // DB-Register
 
      LAR1  #AR1_REGISTER; // AR1-Register
 
END_FUNCTION

Gruß Kai
 

Anhänge

  • OB1.pdf
    5,9 KB · Aufrufe: 33
  • FC100.pdf
    7,1 KB · Aufrufe: 40
  • DB100.pdf
    4,7 KB · Aufrufe: 33
  • Werte.zip
    33,3 KB · Aufrufe: 25
Und noch zwei Bilder aus der Simulation mit PLCSIM.

Gruß Kai
 

Anhänge

  • PLCSIM_1.jpg
    PLCSIM_1.jpg
    341,4 KB · Aufrufe: 59
  • PLCSIM_2.jpg
    PLCSIM_2.jpg
    342,4 KB · Aufrufe: 59
EDIT: @Kai's FC_Werte (s. o.)

Code:
      L     P##ARRAY_WERTE; // Pointer
      LAR1  ; 

      L     [COLOR=#ff0000]W [AR1,P#0.0][/COLOR]; // DB-Nummer [COLOR=#ff0000]--> Warum steht hier die DB-Nummer ? [COLOR=#ff0000]In welchem Speicherbereich bin ich hier? Wo ist sowas dokumentiert ?[/COLOR][/COLOR]
      T     #DB_NUMMER; 

      AUF   DB [#DB_NUMMER]; 

      L     [COLOR=#ff0000]D [AR1,P#2.0][/COLOR]; // Bereichszeiger [COLOR=#ff0000]--> Warum steht hier der Bereichszeiger ? In welchem Speicherbereich bin ich hier? Wo ist sowas dokumentiert ?[/COLOR]
      LAR1  ;
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
      L     P##ARRAY_WERTE; // Pointer
      LAR1  ; 

      L     [COLOR=#ff0000]W [AR1,P#0.0][/COLOR]; // DB-Nummer [COLOR=#ff0000]--> Warum steht hier die DB-Nummer ? [COLOR=#ff0000] In welchem Speicherbereich bin ich hier? Wo ist sowas dokumentiert ?[/COLOR][/COLOR]
      T     #DB_NUMMER; 

      AUF   DB [#DB_NUMMER]; 

      L     [COLOR=#ff0000]D [AR1,P#2.0][/COLOR]; // Bereichszeiger [COLOR=#ff0000]--> Warum steht hier der Bereichszeiger ? In welchem Speicherbereich bin ich hier? Wo ist sowas dokumentiert ?[/COLOR]
      LAR1  ;


Stichwort "anypointer".
Und wenn du uns schreibst woher du den Pointer hast, kann dir noch besser geholfen werden.
Es scheint so, als ob du dir ein Programmteil von irgendwo her kopiert hast, der mit diesem Pointer einen der schönen? SFC versorgen.
Könnte von mir sein, wobei es bestimmt tausende Programmzeilen gibt die mehr oder weniger so ausschauen.
Es gibt doch hier auch ein how to do von Volker hier? :confused:

Schreib zusammenhängend, wo du was her kopiert hast und was du nicht verstehst.
Also den gesamten Code, damit man sieht was du überhaupt willst.


bike
 
@bike
Den Code hat er von Kai hier vom Beitrag #9 zitiert/kopiert.
Es handelt sich nicht um einen ANY-Pointer.

@flux
Das Array wird per Pointer an den FC übergeben (das wird bei jedem Datentyp > 4 Byte so gemacht).
Schau Dir in der Step7-Hilfe den Aufbau des Datentyps POINTER an (Index > Pointerformat > Format des Parametertyps POINTER).

Harald
 
Ich hatte dasgleiche in einem FB versucht (also L P##oINT_IDB_NO; LAR1; L W [AR1,P#0.0]; T #oINT_IDB_NO), was aber nur den Wert 0 hervorgebracht hat. Der Pointer erklärt es, da INT <= 4 Byte (liegt die Grenze bei 4 Byte, weil das die AKKU-Breite ist ?)

L DBNO; T #oINT_IDB_NO; führte ebenfalls nicht zum Ziel - was macht L DBNO denn dann genau ??

Meine Frage ist, wie kann ich zur Laufzeit die IDB-Nummer meiner FB-Instanz bestimmen ?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Meine Frage ist, wie kann ich zur Laufzeit die IDB-Nummer meiner FB-Instanz bestimmen ?
Code:
L DINO
Allerdings ist das nur die halbe Wahrheit. Bei multiinstanzfähigen FB steht die Anfangsadresse der Instanz (Offset im Mutter-IDB) in AR2.


was macht L DBNO denn dann genau ??
Tippe "L DBNO" in den AWL-Editor und drücke F1, das gleiche auch mit "L DINO"
oder Hilfe zu AWL > Inhalt > AWL-Operationen Übersicht > ... sortiert nach deutscher Mnemonik (SIMATIC)
AWL-Operationen sortiert nach deutscher Mnemonik (SIMATIC) schrieb:
L DBNO Lade Nummer Global-DB in AKKU 1
L DINO Lade Nummer Instanz-DB in AKKU 1


Der Pointer erklärt es, da INT <= 4 Byte (liegt die Grenze bei 4 Byte, weil das die AKKU-Breite ist ?)
Nicht ganz.
Elementare Datentypen werden als Wert (Kopie, ByVal) übergeben.
Zusammengesetzte Datentypen werden als POINTER (Referenz, ByRef) übergeben.

Harald
 
Nochmal ne Frage zu o. g. Code:
Code:
      L     P##ARRAY_WERTE; // Pointer: Gehen hierbei nicht Byte 4 und 5 des Pointer verloren, da der AKKU1 nur 4 Byte groß ist ??
      LAR1  ; 


      L     W [AR1,P#0.0]; // DB-Nummer: die ersten zwei Byte im Pointer
      T     #DB_NUMMER; 


      AUF   DB [#DB_NUMMER]; 


      L     D [AR1,P#2.0]; // Bereichszeiger: siehe [B]Frage [/B]
      LAR1  ;

      L     #WERT                       
      T     DBD [AR1,P#0.0]          // DBD bezieht sich auf das zuvor geladene DB-Register

Frage:
Bezieht sich diese Anweisung 1. auf das zuvor geladene DB-Register oder liest es 2. einen Teil aus dem Pointer?
Wenn 1, müsste es dann nicht DBD [...] heissen ?
Wenn 2., warum heisst es dann nicht L B [AR1, P#2.0], wenn nur der Bereichszeiger gemeint ist ? Laut Pointer-Format-Doku steht im Byte 2 der Speicherbereich.
 
Zurück
Oben