Rezept aus einem Quell-DB in einen Ziel-DB übertragen

viktor8313

Level-1
Beiträge
11
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich habe ein kleines Problem. Es ist mir klar, dass es schon genug Beiträge gab, die sich mit dem Thema Zeiger
und inderekte Registeradressierung beschäftigten. Ich benötige paar Antworten von erfahrenen Fachleuten
Ich habe mir Zwar ein schönes Buch besorg, welches sich mit dem Thema SPS-Programmierung beschäftigt.
In diesem Buch wird leider nicht alles gut genug erklär so, dass sich noch eine oder andere Frage ungeklärt bleibt.

Ich versuche gerade eine Art Rezeptverwaltung als Funktion zu programmieren.

Es gibt 4 Rezeptbausteine(vorerst) sowie einen Ziel DB, diese sollen über IN Variablen von Typ Block_DB übergeben werden.
über eine Variable Rezept NR möchte ich daten aus dem gewählten Rezept DB bestimte anzahl von Bytes in eienen Ziel DB kopieren.
Ziel- und Rezept-DBs sind gleich groß und mit gleicher Struktur.

Im buch werden nur Beispiele mit fest vorgegebenen DBs bzw. Beispiele wo ich aus DB Nummer mir eine Adresse baue und in den Adressregister lade aufgeführt.

Wie kann ich Adresse der Quelle als Parameter übergeben? Wie kann ich am besten daten in schleife Byte für Byte kopieren?
Meine adressierung klappt ebenfalls nicht?
Kann mir jemad ein paar Tipps geben?

Ich programmiere sonst Mikrocontroller in C, deshalb erscheinen mir einige Sachen höchst ungewöhnlich.

Code:
IN_VAR
PRG_LOAD          BOOL                //Programm laden
REZEPT_NR         INT                  //Rezeptnummer 1..4
BLOCK_GR           INT                 //Anzahl zu kopierender Bytes
DEST_DB            BLOCK_DB         //Ziel DB
REZEPT1            BLOCK_DB         //Rezept DB1
REZEPT2            BLOCK_DB         //Rezept DB2
REZEPT5            BLOCK_DB         //Rezept DB3
REZEPT4            BLOCK_DB         //Rezept DB4

TEPM_VAR
QADR_DB            DWORD            //Speichert die Adresse des gewählten Quell DBs
Zaehler              INT                 //Schleifenzähler



      U     #PRG_LOAD                 //bei 1 Signal Rezept übertragen
      SPBN  M099

      S     #BUSY                       //Übertragung beginnt, BUSY auf TRUE

//#####[Rezeptnummer 1]#####################################################
      L     #REZEPT_NR
      L     1
      ==I   
      SPB   M001

//#####[Rezeptnummer 2]#####################################################
      L     #REZEPT_NR
      L     2
      ==I   
      SPB   M002

//#####[Rezeptnummer 3]#####################################################
      L     #REZEPT_NR
      L     3
      ==I   
      SPB   M003

//#####[Rezeptnummer 4]#####################################################
      L     #REZEPT_NR
      L     4
      ==I   
      SPB   M004

//##########################################################################
//# Adresse des REZEPT DBs sichern
//##########################################################################

M001: AUF   #REZEPT1                    //Adresse des 1. Rezept DBs sichern
      TAR1  
      T     #QADR_DB
      SPA   M005

M002: AUF   #REZEPT2                    //Adresse des 2. Rezept DBs sichern
      TAR1  
      T     #QADR_DB
      SPA   M005

M003: AUF   #REZEPT3                    //Adresse des 3. Rezept DBs sichern
      TAR1  
      T     #QADR_DB
      SPA   M005

M004: AUF   #REZEPT4                    //Adresse des 4. Rezept DBs sichern
      TAR1  
      T     #QADR_DB
      SPA   M005

//##########################################################################
//# Programmschleife
//#
//# Übertrage Daten anzahl Bytes(BLOCK_GR) aus Rezept-DB(REZEPT#) in Ziel-DB
//##########################################################################

M005: L     #BLOCK_GR
      T     #Zaehler

      LAR1  #QADR_DB
      AUF   #DEST_DB

M006: L     B [AR1,P#0.0]
      T     B [AR2,P#0.0]

      +AR1  P#1.0
      +AR2  P#1.0

      L     #Zaehler
      LOOP  M006

M099: R     #BUSY                       //Programm beendet, BUSY auf FALSE
 
Zuletzt bearbeitet:
Auf den ersten Blick:
-Deine Marke M005 sitzt falsch, weil du sonst stets den Zähler immer wieder auf den Ausgangswert lädst
- Wo wird dein AR2 geladen ?

Hier eine HILFE
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Deine Schleife zum kopieren der Daten passt überhaupt nicht zusammen.
Hast du dir vorgenommen das unbedingt mit registerindirekter Adressierung zu programmieren?
Wenn nein kannst du das nämlich (für meinen Geschmack) einfacher mit speicherindirekter Adressierung umsetzen.

Wenn dein Programm in einem FC läuft kannst du den Umstand ausnutzen dass du zwei Datenbausteine gleichzeitig aufschlagen kannst, nämlich den einen als DB und den anderen als DI.
Code:
      AUF   #DEST_DB                    // Quell DB als DB aufschlagen
      AUF   DI [#ZADR_DB]               // Ziel DB als DI aufschlagen

Das übertragen der Bytes ginge dann in der Schleife mit:
Code:
      L     DBB [#ADR]                  // Byte aus Quell DB laden
      T     DIB [#ADR]                  // und in Ziel DI transferieren

Die Variable #ADR gibt die Adresse an. Dabei ist zu beachten dass die untersten 3 Bits für die Bitadressen zuständig sind. Um also ein Byte Nr. 10 zu laden musst du das mit SLD3 zur korrekten Adresse werden lassen.
 
Wird er nicht beim aufschalgen des Ziel-DBs geladen oder muss ich ihn extra mit der Adresse füttern?

Ich möchte eigentlich sowohl Rezept DBs als auch Ziel DB als globale DB nutzen da ein mein Programm auf den Ziel-DB zugreifen soll und nur die Werte der Rezept-DBs in diesen kopieren möchte
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Aber wie kann ich den in mein Konzept einbinden, der SFC20 benötigt nur eine DB-Nummer, oder? Ich kann dort nicht meiene Eingangsvariablen benutzen?
wie kann ich aus Block_DB die aktuelle DB-Nummer rausfinden?

Ich habe mir das eigentlich deutlich einfacher vorgestellt, aber ich will ja was dabei lernen.:D
 
Der SFC20 benötigt DB-Nr. und die Anzahl der zu kopierenden Bytes.

Schau dir die Hilfe in STEP7 mittels F1-Taste an, dort sind Beispiele.
Auf die Schnelle noch eine weitere Hile ergänzend zu dem Link aus Beitrag #2: LINK
 
Ähnliche hatten wir ja schon des öfteren.
In diesem Beitrag #9 ist ein Bsp. für Block_move programmiert.
Diesen FC kann man nutzen, ohne dann selbst indirekt adressieren zu müssen oder Any-Pointer zubauen.
Man gibt DB-Nr, Start DBB, Anzahl der DBB für Ziel und Quelle an und kopiert die Daten um, fertig.
 
Also zuerst möcht ich euch allen für eure Bemühungen mir zu helfen danken!

Ich arbeite mit Step7 v5.5 SP2 und habe kein SCL. Könnte ich das auf der Weise wie ich ich oben angefangen habe das so umsetzen?
Ich habe jetzt mein bisherigen Code geändert.

Wie kann ich aus der Eingangsvariable vom Typ Block_DB die Nummer des angeschlossenen DBs rauskriegen?
Würde die Schleife so passen? an M001 bis M004 muss ich ja die eigentliche DB Nummer rausfinden in einer Word Variablen speichern und
dann in meiner Schleife mit AUF [DB_NR], DB_NR als WORD, den entsprechenden DB öffnen? oder?

Code:
      U     #PRG_LOAD
      SPBN  M099

      S     #BUSY                       //Übertragung beginnt, BUSY auf TRUE

//#####[Rezeptnummer 1]#####################################################
      L     #REZEPT_NR
      L     1
      ==I   
      SPB   M001

//#####[Rezeptnummer 2]#####################################################
      L     #REZEPT_NR
      L     2
      ==I   
      SPB   M002

//#####[Rezeptnummer 3]#####################################################
      L     #REZEPT_NR
      L     3
      ==I   
      SPB   M003

//#####[Rezeptnummer 4]#####################################################
      L     #REZEPT_NR
      L     4
      ==I   
      SPB   M004

//##########################################################################
//# Adresse des REZEPT DBs sichern
//##########################################################################

M001: AUF   #REZEPT1                    //Adresse des 1. Rezept DBs sichern
      L DBNO  
      T     #QDB_NR
      SPA   M005

M002: AUF   #REZEPT2                    //Adresse des 2. Rezept DBs sichern
      L DBNO
      T     #QDB_NR
      SPA   M005

M003: AUF   #REZEPT3                    //Adresse des 3. Rezept DBs sichern
      L DBNO
      T     #QDB_NR
      SPA   M005

M004: AUF   #REZEPT4                    //Adresse des 4. Rezept DBs sichern
      L DBNO  
      T     #QDB_NR
      SPA   M005

//##########################################################################
//# Programmschleife
//#
//# Übertrage Daten anzahl Bytes(BLOCK_GR) aus Rezept-DB(REZEPT#) in Ziel-DB
//##########################################################################

M005: L     #BLOCK_GR
      T     #Zaehler

      LAR1  P#0.0


M006: AUF   DB [#QDB_NR]               //QuellDB aufschalgen
      L     DBB [AR1,P#0.0]

      AUF   #DEST_DB                   //Ziel DB aufschalgen
      T     DBB [AR1,P#0.0]

      +AR1  P#1.0                       //Registerwert ein Byte weiter

      L     #Zaehler
      LOOP  M006

M099: R     #BUSY                       //Programm beendet, BUSY auf FALSE
 
Zuletzt bearbeitet:
Ich möchte gerne ein wenig experemntieren und paar Sachen ausprobieren und nebenbei was dazu zu lernen.:D

Ich bekomme noch ein Problem mit dem Adresszeiger, es kommt zum Bereichslesefehler im PLCSim.
Was muss ich jetzt noch beachten(s. Beitrag #11 ist der aktuelle Code)?
 
Aber wie kann ich den in mein Konzept einbinden, der SFC20 benötigt nur eine DB-Nummer, oder? Ich kann dort nicht meiene Eingangsvariablen benutzen?
wie kann ich aus Block_DB die aktuelle DB-Nummer rausfinden?

Ich habe mir das eigentlich deutlich einfacher vorgestellt, aber ich will ja was dabei lernen.:D

Code:
 AUF   #DB_Nummer
      L     DBNO
      T     #pt_DB //INT-Variable

Ich bekomme noch ein Problem mit dem Adresszeiger, es kommt zum Bereichslesefehler im PLCSim.

Stimmt der Wert in "BLOCK_GR"?

Sicherheitshalber solltest Du "TEST_DB" nutzen, um:

a) abzufragen, ob der DB vorhanden ist
b) die Länge auszulesen.

Code:
  CALL  "TEST_DB"
       DB_NUMBER :=#pt_DB
       RET_VAL   :=#RET_VAL_SFC24
       DB_LENGTH :=#DB_Laenge
       WRITE_PROT:=#DB_WP
      NOP   0

// DB_Laenge übertragen:
L #DB_Laenge
T #Zaehler

 
Zuviel Werbung?
-> Hier kostenlos registrieren
wie kann ich aus Block_DB die aktuelle DB-Nummer rausfinden?

vielleicht einfach so:
AUF #DEST_DB
L DBNO
T in eine INT variable; da ist dann die db nummer
und mit
L DBLG
T in eine INT variable; da ist dann die db länge (warscheinlich in bytes)

(jetzt) nicht ausprobiert (irgendwann vor jahren mal) ; alles aus der S7 Hilfe:
[ bei "AUF" F1 gedrückt, dann "Inhalt" , dort "DB-Operationen" ]
--------------------------------------------------------------------------------------------------
L DBNO (Lade die Nummer des Global-Datenbausteins) lädt die Nummer des geöffneten Global-Datenbausteins in AKKU1, nachdem zuvor der Inhalt von AKKU 1 in AKKU 2 gespeichert wurde.
--------------------------------------------------------------------------------------------------
L DBLG (Lade die Länge des Global-Datenbausteins) lädt die Länge des Global-Datenbausteins in AKKU 1, nachdem zuvor der Inhalt von AKKU 1 in AKKU 2 gespeichert wurde.
--------------------------------------------------------------------------------------------------
 
Ich habe noch eine kleine Frage. Was ich nicht ganz verstehe und bis jetzt nirgendwo gefunden habe ist die Tatsache, dass ich nicht genau weiß wann die Adresse in den Adressregister geladen wird?

Wenn ich z.B. den DB aufschlage und daten aus dem DB lese dann muss doch schon die absolute Adresse des Datenbausteins im AR befinden oder nicht?
 
Steht eigentlich im obigen Beispiel drin:


AUF DB [#QDB_NR] //QuellDB aufschalgen
L DBB [AR1,P#0.0]

AUF DB - hat so erstmal nichts mit
L DBB xxx
zu tun

anders das:
L DB10.DBB5

das ergibt "eigentlich" :
AUF DB 10
L DBB5

LAR1 P#0.0
lädt ins AR nur einen Zeiger auf eine Adresse in einen DB der zum zeitpunkt von
L DBB [AR1,P#0.0]
dann eben gerade offen ist.

neben
DBB [AR1,P#0.0]
gibt es noch
L DBW [AR1,P#0.0]
L DBD [AR1,P#0.0]
U DBX [AR1,P#0.0] hier ist dann auch .x relevant
so dann auch
L MB [AR1,P#0.0]
L MW [AR1,P#0.0]
L MD [AR1,P#0.0]
U M [AR1,P#0.0] das selbe statt mit DB mit Merkern

obigen Beispiel - Zitat:
Code:
M005: L     #BLOCK_GR
      T     #Zaehler

      LAR1  P#0.0

M006: AUF   DB [#QDB_NR]               //QuellDB aufschalgen
      L     DBB [AR1,P#0.0]

      AUF   #DEST_DB                   //Ziel DB aufschalgen
      T     DBB [AR1,P#0.0]

      +AR1  P#1.0                       //Registerwert ein Byte weiter

      L     #Zaehler
      LOOP  M006
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke Senator42!

Die Beispiele die Du aufgeführt hast kenne ich bereits aus meinem Buch. Ich habe jedoch irgendwie anscheinend ein Problem beim Lesen, denn die CPU(PLCSim) geht auf Stop und bei der Diagnose finde ich immer einen Fehler, Breichslesefehler vor?

Ich habe jetzt mich anhand eines Beispiels von SoftMachine aus Beitrag#7 orientiert und folgendermaßen gelöst.
Zum kopieren verwende ich SFC20 "BLKMOV" und baue mir zwei Pointer vom Typ ANY, wie in der Siemens-Hilfe beschrieben.(Danke SoftMachine!)

Code:
      U     #PRG_LOAD
      SPBN  M099

      S     #BUSY                       //Übertragung beginnt, BUSY auf TRUE

      L     0
      T     #SRC_DB_NR
      T     #DST_DB_NR
      T     #BLKMOV_RetVal

//#####[Rezeptnummer 1]#####################################################
      L     #REZEPT_NR
      L     1
      ==I   
      SPB   M001

//#####[Rezeptnummer 2]#####################################################
      L     #REZEPT_NR
      L     2
      ==I   
      SPB   M002

//#####[Rezeptnummer 3]#####################################################
      L     #REZEPT_NR
      L     3
      ==I   
      SPB   M003

//#####[Rezeptnummer 4]#####################################################
      L     #REZEPT_NR
      L     4
      ==I   
      SPB   M004

//##########################################################################
//# Adresse des REZEPT DBs sichern
//##########################################################################

M001: AUF   #SRC_DB1                    //Adresse des 1. Rezept DBs sichern
      L     DBNO
      T     #SRC_DB_NR
      SPA   M005

M002: AUF   #SRC_DB2                    //Adresse des 2. Rezept DBs sichern
      L     DBNO
      T     #SRC_DB_NR
      SPA   M005

M003: AUF   #SRC_DB3                    //Adresse des 3. Rezept DBs sichern
      L     DBNO
      T     #SRC_DB_NR
      SPA   M005

M004: AUF   #SRC_DB4                    //Adresse des 4. Rezept DBs sichern
      L     DBNO
      T     #SRC_DB_NR
      SPA   M005

//##########################################################################
//# Programmschleife
//#
//# Übertrage Daten anzahl Bytes(BLOCK_GR) aus Rezept-DB(REZEPT#) in Ziel-DB
//##########################################################################

M005: NOP   0
      AUF   #DSC_DB
      L     DBNO
      T     #DST_DB_NR

// Build Anypointer Source
      L     P##PSrc
      LAR1  
// System-Code
      L     B#16#10
      T     B [AR1,P#0.0]
// Datatype Byte
      L     B#16#2
      T     B [AR1,P#1.0]
// Number of Bytes to Copy
      L     #BLOCK_GR
      T     W [AR1,P#2.0]
// DB-Nr of Source Datablock
      L     #SRC_DB_NR
      T     W [AR1,P#4.0]
// Begin at DBX0.0
      L     P#DBX 0.0
      T     D [AR1,P#6.0]


// Build Anypointer Destination ############################################
      L     P##PDsc
      LAR1  
// System-Code
      L     B#16#10
      T     B [AR1,P#0.0]
// Datatype Byte
      L     B#16#2
      T     B [AR1,P#1.0]
// Number of Bytes to Copy
      L     #BLOCK_GR
      T     W [AR1,P#2.0]

// DB-Nr of Destination Datablock
      L     #DST_DB_NR
      T     W [AR1,P#4.0]
// Begin at DBX0.0
      L     P#DBX 0.0
      T     D [AR1,P#6.0]


// Blockmove, Transfer Data ################################################
      CALL  "BLKMOV"
       SRCBLK :=#PSrc
       RET_VAL:=#BLKMOV_RetVal
       DSTBLK :=#PDsc


M099: R     #BUSY                       //Programm beendet, BUSY auf FALSE

Ich danke euch allen, Ihr habt mir sehr geholfen!!!:D
 
Zuletzt bearbeitet:
Ich habe jetzt mich anhand eines Beispiels von SoftMachine aus Beitrag#7 orientiert und folgendermaßen gelöst.
Zum kopieren verwende ich SFC20 "BLKMOV" und baue mir zwei Pointer vom Typ ANY, wie in der Siemens-Hilfe beschrieben.(Danke SoftMachine!)

Ich danke euch allen, Ihr habt mir sehr geholfen!!!

Danke für die Blumen !
Gern geschehen, so soll es ein, dafür ist dieses Forum da :D
 
Zuletzt bearbeitet:
Zurück
Oben