Array Element über Variable auslesen.

FriedelM

Level-1
Beiträge
4
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

Bisher habe ich nur in ST programmiert und soll mich nun in der S7 einarbeiten deshalb habe ich zwei einfache Fragen:
Meine Steuerung ist eine S7 315 DP.
Das Programm soll in AWL geschrieben werden.
Problem 1:
Ich habe im DB14 ein Array [0...15] of Int. in diesem möchte ich über eine Variable ein einzelnes Element auslesen.
In ST wäre das folgendermaßen:
Wertx:=Array[variable_X];

Mein zweites Problem ist etwas komplexer. Hier habe ich ebenfalls ein Array [0...6] of Int. Dieses möchte ich mit einer Schleife durchlaufen und Bitweise abfragen. Sollte ein Bit true sein möchte ich die Bittnummer in einen anderes Array mit 16 Feldern schreiben.
Beispiel:
Das Bit 5, 16, 25 ,33 und 36 ist true.

(0000 0100 0000 0000 1000 0000 0100 0000 0100 1000 ..........)
Dann soll in einen Integer die ersten 5 bits true gesetzt werden. (0000 0000 0001 1111) bei 6 Bits die true sind dem entsprechend die ersten sechs.
Das Array soll dann so aussehen.
Array[0] := 5;
Array[1] := 16;
Array[2] := 25;
Array[3] := 33;
Array[4] := 36;
Sollten mehr als 16 Bits true sein, werden ab dem 16. Bit, diese nicht mehr beachtet.

Vielen Dank für eure Hilfe im Voraus. Und denkt daran ich bin nicht besonders fit beim S7 programmieren

.
 
Hallo,

Wenn du weißt, welches Element du auslesen willst würde ich das mit "lade" und "transferiere" machen.

L db14.dbwx
T variable

Deiner zweiten Frage kann ich nicht folgen. Aber es hört sich für mich nach indirekter Adressierung mit Zeigern an, ...

Gruß Copy
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Suche mal in der Step7-Hilfe nach Adressierung speicherindirekt, das kommt der Array-Schreibweise schon ziemlich nahe, adressiert aber nicht ein Array-Element sondern eine Speicheradresse in Byte-Zählung. EDIT: Bit-Zählung.

Harald
 
Zuletzt bearbeitet:
Problem 1:
Das indirekte Adressieren des "Index" in der eckigen Klammer hätte ich auch schon x-mal mit AWL/KOP/FUP gebrauchen können... :?
Wie PN/DP schon geschrieben hat, kann man nur die Adresse aufrufen. Wenn dann mal ein Element eingefügt wird, passen die Adressen nicht mehr.

Problem 2:
Könnte man mit einer Schleife lösen (AWL kann "LOOP" :D).
Bits mit einem Schiebebefehl durchschieben, das letzte Bit auf 1 abfragen und den Schleifenzähler benutzen, um einzutragen das wievielte bit an war.
 
Hallo,
vielleicht noch ein anderer Ansatz :
das Pendant zu ST gibt es in der Siemens-Welt auch - nennt sich da SCL. Da solltest du dann alles so machen können wie gehabt.
Unter Siemens AWL kannst du die Adressierung nur wie oben beschrieben über indirekte Adressierung lösen (also für jedes Array-Element einen neuen Pointer bauen). Du kannst hier (leider) nicht mit dem Index direkt arbeiten ...

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Versuche zu Problem 1

Hallo ich habe nach ein paar Versuchen folgenden Code erstellt der nciht funktioniert.:confused: Den habe ich mir aus anderen Forenbeiträgen zusammengesucht.

Code:
AUF   "Fehlerauswertung" //DB 14
      L     "Fehlerauswertung".FehlerDetailAnzeige //DB 14.dbw34
      T     #akt_dw 
      SLD   3
      LAR1  
      L     DBD [AR1,P#0.0]
      T     "Fehlerauswertung".FehlerDetailAnzeige //DB 14.dbw36
Dabei geht die CPU immer in Stopp.
Ich finde einfach nichts für die richtige Syntax.
Ich habe ach andere Versuche gemacht, dabei kommen dann allerdings immer wirre Werte raus.
Leider habe ich hier nur die Möglichkeit in AWL zu programmieren.
Und unter "Adressierung speicherindirekt" habe ich nichts gefunden. :confused:

Gruß FriedelM
 
Hallo ich habe nach ein paar Versuchen folgenden Code erstellt der nciht funktioniert.:confused: Den habe ich mir aus anderen Forenbeiträgen zusammengesucht.

Code:
AUF   "Fehlerauswertung" //DB 14
      L     "Fehlerauswertung".FehlerDetailAnzeige //DB 14.db[COLOR="Red"]w[/COLOR]34
      T     #akt_dw 
      SLD   3
      LAR1  
      L     DB[COLOR="#ff0000"]D[/COLOR] [AR1,P#0.0]
      T     "Fehlerauswertung".FehlerDetailAnzeige //DB 14.db[COLOR="#ff0000"]w[/COLOR]36
Dabei geht die CPU immer in Stopp.
Ich finde einfach nichts für die richtige Syntax.
Ich habe ach andere Versuche gemacht, dabei kommen dann allerdings immer wirre Werte raus.
Leider habe ich hier nur die Möglichkeit in AWL zu programmieren.
Und unter "Adressierung speicherindirekt" habe ich nichts gefunden. :confused:

Gruß FriedelM

Sollte da nicht ein

Code:
L DBW (AR1.P#0.0)

rein?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

Ich habe da zwei ganz "dumme" Fehler gemacht. Jetzt funktioniert es *ROFL*
Hier der richtige Code. Woran ich nicht gedacht habe, ist dass ich bei der Adressierung ja nor jede 2. Adresse abfragen kann.
Code:
      AUF   "Fehlerauswertung" //
      L     "Fehlerauswertung".FehlerDetailBild
      T     #akt_dw
      SLD   3
      LAR1  
      L     DBW [AR1,P#0.0]
      T     "Fehlerauswertung".FehlerDetailAnzeige
Zu Problem 2 komme ich dann noch einmal später. Vielen Dank an euch. Muss leider noch an einen anderen Projekt weiter machen. Der BL ruft.

Gruß FriedelM
 
Ich habe im DB14 ein Array [0...15] of Int. in diesem möchte ich über eine Variable ein einzelnes Element auslesen.
In ST wäre das folgendermaßen:
Wertx:=Array[variable_X];
Hier der richtige Code. Woran ich nicht gedacht habe, ist dass ich bei der Adressierung ja nor jede 2. Adresse abfragen kann.
Code:
      AUF   "Fehlerauswertung" //
      L     "Fehlerauswertung".FehlerDetailBild
      T     #akt_dw
      SLD   [COLOR="red"]3   // muß [B]SLD 4[/B] heißen bei INT-Array[/COLOR]
      LAR1
      L     DBW [AR1,P#0.0]
      T     "Fehlerauswertung".FehlerDetailAnzeige
SLD 3 adressiert byteweise, SLD 4 adressiert wordweise.

Mit SLD 4 entspricht das der Operation "Fehlerauswertung".FehlerDetailAnzeige:=Array["Fehlerauswertung".FehlerDetailBild]; wenn Dein Array bei DB14.DBB0 beginnt. Wenn das Array nicht bei DBB0 beginnt, dann muß zwischen dem SLD 4 und dem LAR1 noch die Anfangsadresse des Arrays addiert werden.

Harald
 
Schon etwas länger her...

... aber ich hab mal so etwas gebastelt:

Code:
FUNCTION "READ_IND_ADR_ARRAY" : VOID
TITLE =
VERSION : 0.1


VAR_INPUT
  feld_nr : INT ;	//Gewünschtes Feld im INTEGER-Format.
  feld_laeng : INT ;	//Summe über die Länge aller Zellen  innerhalb eines Feldes Byte-Weise.  
END_VAR
VAR_OUTPUT
  aus_zelle1 : TIME ;	//Inhalt des ersten ARRAY-Elements, das  gelesen werden soll.  
END_VAR
VAR_IN_OUT
  feld : ARRAY  [1 .. 100 ] OF //Muß identisch sein mit dem ARRAY, auf dem indirekt zugegriffen werden soll!
  STRUCT 	
   feld1 : TIME ;	
  END_STRUCT ;	
END_VAR
VAR_TEMP
  dbnr : WORD ;	
  offset : DWORD ;	
END_VAR
BEGIN
NETWORK
TITLE =OFFSET ermitteln

//ermitteln des gewünschten Feldes, auf das zugegriffen werden soll
//nach folgendem Algorithmus: (feld_nr - 1) * feld_laeng 

      L     #feld_nr; // Gewünscht. Indize vom ARRAY z.B.: 1 - 4
      L     1; 
      -D    ; 
      L     #feld_laeng; // Länge des Feldes Byteweise in
      *D    ; // INT-Format z.B.: 4 da 2 mal INTEGER.
      SLD   3; // Um 3 Bit nach links schieben um
      T     #offset; // Pointer-Format zu erhalten.

NETWORK
TITLE =Lesen indirekt Impliziert ARRAY-Feld 


      L     P##feld; // Ermitteln der Anfangsadresse.
      LAR1  ; // Laden der Anfangsadresse in das Adressregister 1.
      L     W [AR1,P#0.0]; // Falls ein referenzierter Zugriff erfolgt: DB-Nr. ermitteln.
      T     #dbnr; // Sichern der DB-Nr.
      AUF   DB [#dbnr]; // DB öffnen.
      L     #offset; // Lade OFFSET.
      L     D [AR1,P#2.0]; // Laden der Anfangsadresse des ARRAYs.
      +D    ; // Verknüpfen mit Anfangsadresse des Feldes.laden der Adresse des indizierten Feldes
      LAR1  ; // in das Adressregister 1.
      L     D [AR1,P#0.0]; // Ausgabe des Inhaltes des gewünschten
      T     #aus_zelle1; // Feldes zur OUTPUT-Variablen.

END_FUNCTION

FUNCTION "WRITE_IND_ADR_ARRAY" : VOID
TITLE =
VERSION : 0.1


VAR_INPUT
  feld_nr : INT ;	//Gewünschtes Feld im INTEGER-Format.
  feld_laeng : INT ;	//Summe über die Länge aller Zellen  innerhalb eines Feldes Byte-Weise.  
  in_zelle1 : TIME ;	//Inhalt des ersten ARRAY-Elements, das  beschrieben werden soll.  
END_VAR
VAR_IN_OUT
  feld : ARRAY  [1 .. 100 ] OF //Muß identisch sein mit dem ARRAY, auf dem indirekt zugegriffen werden soll!
  STRUCT 	
   feld1 : TIME ;	
  END_STRUCT ;	
END_VAR
VAR_TEMP
  dbnr : WORD ;	
  offset : DWORD ;	
END_VAR
BEGIN
NETWORK
TITLE =OFFSET ermitteln

//ermitteln des gewünschten Feldes, auf das zugegriffen werden soll
//nach folgendem Algorithmus: (feld_nr - 1) * feld_laeng 

      L     #feld_nr; // Gewünscht. Indize vom ARRAY z.B.: 1 - 4
      L     1; 
      -D    ; 
      L     #feld_laeng; // Länge des Feldes Byteweise in
      *D    ; // INT-Format z.B.: 4 da 2 mal INTEGER.
      SLD   3; // Um 3 Bit nach links schieben um
      T     #offset; // Pointer-Format zu erhalten.

NETWORK
TITLE =schreiben indirekt impliziet ARRAY-Feld 


      L     P##feld; // Ermitteln der Anfangsadresse.
      LAR1  ; // Laden der Anfangsadresse in das Adressregister 1.
      L     W [AR1,P#0.0]; // Falls ein referenzierter Zugriff erfolgt: DB-Nr. ermitteln.
      T     #dbnr; // Sichern der DB-Nr.
      AUF   DB [#dbnr]; // DB öffnen.
      L     #offset; // OFFSET laden.
      L     D [AR1,P#2.0]; // Laden der Anfangsadresse des ARRAYs.
      +D    ; // Verknüpfen mit Anfangsadresse des Feldes. Laden der Adresse des indizierten Feldes
      LAR1  ; // in das Adressregister 1.
      L     #in_zelle1; 
      T     D [AR1,P#0.0]; // Ausgabe des Inhaltes des gewünschten

END_FUNCTION

Gruß

Stefan
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

Endlich bin ich dazu gekommen, dass Programm fertig zu programmieren.
Ich habe nur das Problem, dass High Byte und Low Byte vertauscht sind. Aber ich denke, dass ich dazu, noch eine Lösung finde.

Code:
      AUF   "DB55_HMI_Störmeldungen"
      L     #akt_dw_loop
      L     95
      >=I   
      SPBB  lasb                        //letztes Bit
//Abfrage der Bitposition
      L     #akt_dw_loop
      LAR1  
      U     DBX [AR1,P#0.0]
      SPBN  inc
//Abfrage ob das Letzte Anzeigefenster erreicht ist
      L     16
      L     #fehler_bit
      ==I   
      SPBB  inc
//Schreibe Fehlernummer ins Array
      AUF   "Fehlerauswertung"
      L     #fehler_bit
      SLD   4
      LAR1  
      L     #akt_dw_loop
      T     DBW [AR1,P#2.0]
      L     #fehler_bit
      LAR1  
      SET   
      =     DBX [AR1,P#0.0]
// fehlerbit +1
      L     1
      L     #fehler_bit
      +I    
      T     #fehler_bit
// akt_dw_loop +1
inc:  L     1
      L     #akt_dw_loop
      +I    
      T     #akt_dw_loop
// Fehler rücksetzten bei Reset
lasb: U     "DB52_HMI_Schalter".Fehler_zuruecksetzten
      SPBNB end
      L     0
      T     #akt_dw_loop
      T     #fehler_bit
      T     "Fehlerauswertung".FehlerSichtbar
end:  BE

Gruß und Vielen Dank für eure Hilfe

Friedel
 
Zurück
Oben