Mehrere Datenbausteine durchsuchen

Zuviel Werbung?
-> Hier kostenlos registrieren
Also ich hab mich jetzt mal mit der Suchfunktion durch einige Beiträge zum Thema "indirekte Adressierung" gekämpft.

Ich denke im Prinzip ist mir das schon klar wie es funktionieren müsste.
In der Praxis will es aber nicht so ganz klappen:

Code:
AUF   DB    30          <-- DB30 öffnen
L     #Ergeb            <-- Eingangswert ist Ergebniss aus Rechenoperation
SLD   3                 <-- 3 nach links schieben, [B]WARUM ??[/B]
L     #Ergeb            <-- Ergebniss nach Akku 1 laden
L     DBD [AR1,P#0.0]   <-- Indirekt Adressiertes DWORD aus DB30 in Akku 1 laden
T     MD   140          <--- Ausgabe Wert aus AR1?
Ich bin mir aber nicht ganz sicher ob das so richtig ist.

Nehmen wir mal an die Eingangsvariable wäre 52 (DWORD) und in DB30.DBD52 steht der Wert 1, so müsste doch am Ende in MD140 der Wert 1 stehen?

Aber da steht als Ergebniss immer 336343346.
Aber warum, was habe ich übersehen?

Indirekte Adressierung ist totales Neuland für mich..

Gruß smartie
 
Achso, ja klar das LAR1 muss noch dazu um den mit SLD 3 erzeugten Pointer in das Adressregister zu übertragen, und anschließend T # Ergeb um es wieder in den Akku zu schieben, oder?

smartie
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Der Programmcode ist so richtig:

Code:
AUF   DB    30          <-- DB30 öffnen
L     #Ergeb            <-- Eingangswert ist Ergebniss aus Rechenoperation
SLD   3                 <-- 3 nach links schieben
LAR1                    <-- Ergebnis nach Akku 1 laden
L     DBD [AR1,P#0.0]   <-- Indirekt Adressiertes DWORD aus DB30 in Akku 1 laden
T     MD   140          <-- Nach MD140 transferieren

Gruß Kai
 
@ marlob:

Ja die FAQ hab ich gelesen, aber als "Indirekt Adressier Anfänger" nicht so ganz verstanden.

Hab mich dann noch an http://sps-forum.de/showthread.php?t=15194&highlight=indirekte+adressierung und der Siemens Online Hilfe orientiert.

@ Kai

So habe ich den Code jetzt auch und es funktioniert.

Wie marlob schon gechrieben hat muss ich mit Ergeb nach LAR1 gar nichts mehr machen, das T #Ergeb entfällt somit.


Danke
 
@smartie

Wenn es dich interessiert, kann ich dir den Code für eine Suchfunktion, wie du sie nutzen könntest als Quelle hier einstellen, wird aber erst spät heute Abend. Muß jetzt los. :rolleyes:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Ralle,

wenn du das machen könntest wäre super. Ich kämpfe gerade gleichzeitig an zwei Problemen. Ich hätte dann zumindest bei der Suchfunktion mal einen Ansatzpunkt.

Heute Nachmittag habe ich dann endlich einen Rückrüf von Siemens bezüglich des Datenempfangs mit dem CP340 erhalten.

Es wäre wohl mit der Benutzung der Datenflusskontrolle möglich mehr als 1024 Zeichen über den CP340 zu empfangen.
Die Funktion RECIEVE gibt ja das NDR Signal aus wenn neue Daten empfangen worden sind.

Nach dem ich das NDR Signal das erste mal erhalten habe müsste ich die Daten in einen zweiten DB verschieben
und angeblich würden dann die restlichen Daten kommen und anschließend noch einmal NDR.

NDR kommt aber nur einmal (hab zur Sicherheit nen Zähler dran), und zwar nur dann wenn das ganze Datentelegramm am CP340 eingetroffen ist.
Es sieht dann so aus das ich von meinen ca. 1600 Zeichen die letzen 580 habe und zwar in beiden DB´s, also die ersten 1024 Zeichen fehlen.


Gruß smartie

(PS.: Zwischendurch schon mal : Danke für eure geduldige Hilfe) :)

smartie
 
So, ich stelle mal den Code eines FB ein, du kannst diesen kopieren und in eine AWL-Quelle einfügen, diese dann übersetzen und du hast in deinem Bausteinordner einen FB110. Diesen rufst du wie folgt auf:

Code:
     CALL  FB   110 , DB110
       DBNr         :=111               //DB111 enthält die Daten vom Cp340
       Scanncode    :="Scanncode".Scanncode    //Definiere dir in einem DB112 den du in der Symbolik "Scanncode" nennst einen 18 Zeichen langen String, den du auch "Scanncode" nennst
       Max_Len      :=12000             //12000 Byte durchsuchen (geht natürlich nur, wenn dein DB111 mind. so lang ist !
       Pos          :=MW2               //Position, an welcher der Code gefunden wurde
       Start        :=M0.0
       Fertig       :=M1.0
       Code_gefunden:=M1.1
Hier der Baustein:

Code:
FUNCTION_BLOCK FB 110
TITLE =
AUTHOR : Ralle
FAMILY : System
NAME : Search
VERSION : 0.9


VAR_INPUT
  DBNr : INT ;                    //DB-Nummer des DB, der durchsucht werden soll
  Scanncode : STRING  [18 ];    //18 Zeichen langer Suchstring
  Max_Len : INT ;                //Wieviele Bytes sollen im DB durchsucht werden?
END_VAR
VAR_OUTPUT
  Pos : INT ;                    //Byte-Nr, an der der Code gefunden wurde
END_VAR
VAR_IN_OUT
  Start : BOOL ;                //einmalig zum Start setzen, wird am Ende vom FB zurückgesetzt
  Fertig : BOOL ;                //Fertigmeldung, wird bei Start immer gelöscht
  Code_gefunden : BOOL ;        //Codevergeleich war positiv, wird bei Start immer gelöscht
END_VAR
VAR
  ddSuch : DWORD ;                //erstes DWord zur Suche
  Zaehler : INT ;                //Suchzähler
END_VAR
VAR_TEMP
  SAVE_VKE : BOOL ;    
  RETTAR1 : DWORD ;    
  RETTAR2 : DWORD ;    
  wDBNo : WORD ;    
  TEMP0 : DWORD ;    
END_VAR
BEGIN
NETWORK
TITLE =

//Sichere VKE im BIE
      SET   ; 
      SAVE  ; 
      =     #SAVE_VKE; 

//Adressregister retten
      TAR1  #RETTAR1; 
      TAR2  #RETTAR2; 

      U     #Start; 
      SPBN  ENDE; 

      L     #DBNr; 
      T     #wDBNo; 
      AUF   DB [#wDBNo];         //globalen DB öffnen

      SET   ; 
      R     #fertig; 
      R     #Code_gefunden; 

      L     P##Scanncode; 
      LAR1  ; 
      L     DID [AR1,P#2.0];     //Instanz-DB, Byte0+1 sind Stringlänge, also gehts bei 2 los
      T     #ddSuch;             //Das ist das erste DWord, das gesucht wird

      L     #Max_Len;             //Maximale Länge der Daten im DB
Z001: T     #Zaehler; 

      L     #Max_Len; 
      L     #Zaehler; 
      -D    ;                     //wir wollen ja bei DBD0 anfangen (bei Bedarf noch ein Offset dazu)
      SLD   3;                     //aus dem Zähler einen Pointer machen
      LAR1  ; 
      L     DBD [AR1,P#0.0]; //globaler DB
      L     #ddSuch; 
      ==D   ; 
      SPB   VERG; 

      L     MD   100; 
      L     1; 
      +D    ; 
      T     MD   100; 

WESU: L     #Zaehler; 
      LOOP  Z001;                 //der Zaehler wird automatisch um 1 dekrementiert (erniedrigt)
      SPA   KCOD;                 //alles durchsucht, aber keine Übereinstimmung gefunden

VERG: NOP   0; 
//18 Zeichen vergleichen
//1 Zeichen entspricht einem Byte, 4 Zeichen haben wir schon, bleiben 14 weitere, macht 3 DWORD + 1 WORD

//Zeichen 5-8
      L     #Max_Len; 
      L     #Zaehler; 
      -D    ; 
      SLD   3; 
      LAR1  ; 
      L     DBD [AR1,P#4.0]; //globaler DB
      T     #TEMP0; 
      L     P##Scanncode; 
      LAR1  ; 
      L     DID [AR1,P#6.0]; //Instanz-DB
      L     #TEMP0; 
      ==D   ; 
      SPBN  WESU;                 //ungleich, also oben weitersuchen mit dem nächsten Byte

//Zeichen 9-12  
      L     #Max_Len; 
      L     #Zaehler; 
      -D    ; 
      SLD   3; 
      LAR1  ; 
      L     DBD [AR1,P#8.0]; 
      T     #TEMP0; 
      L     P##Scanncode; 
      LAR1  ; 
      L     DID [AR1,P#10.0]; 
      L     #TEMP0; 
      ==D   ; 
      SPBN  WESU;                 //ungleich, also oben weitersuchen mit dem nächsten Byte

//Zeichen 13-16
      L     #Max_Len; 
      L     #Zaehler; 
      -D    ; 
      SLD   3; 
      LAR1  ; 
      L     DBD [AR1,P#12.0]; 
      T     #TEMP0; 
      L     P##Scanncode; 
      LAR1  ; 
      L     DID [AR1,P#14.0]; 
      L     #TEMP0; 
      ==D   ; 
      SPBN  WESU;                 //ungleich, also oben weitersuchen mit dem nächsten Byte

//Zeichen 17-18
      L     #Max_Len; 
      L     #Zaehler; 
      -D    ; 
      SLD   3; 
      LAR1  ; 
      L     DBW [AR1,P#16.0]; 
      T     #TEMP0; 
      L     P##Scanncode; 
      LAR1  ; 
      L     DIW [AR1,P#18.0]; 
      L     #TEMP0; 
      ==D   ; 
      SPBN  WESU;                 //ungleich, also oben weitersuchen mit dem nächsten Byte

//18 Zeichen gleich, also Code gefunden und fertig
      SET   ; 
      S     #fertig; 
      S     #Code_gefunden; 
      R     #Start; 
      L     #Max_Len; 
      L     #Zaehler; 
      -D    ; 
      T     #Pos; 
      SPA   ENDE; 

//keine Übereinstimmung gefunden, aber das Ende des Suchbereiches erreicht
KCOD: SET   ; 
      S     #fertig; 
      R     #Code_gefunden; 
      R     #Start; 
      L     0; 
      T     #Pos; 

ENDE: NOP   0; 

//Zurückübertragen der geretteten Adressregister
      LAR1  #RETTAR1; 
      LAR2  #RETTAR2; 

      U     #SAVE_VKE; 
      SAVE  ; 
      BE    ; 
END_FUNCTION_BLOCK
Der FB funktioniert so, kann sicher noch optimiert werden, allerdings vergleicht er alles in einem Rutsch und fängt immer bei DBD0 im zu durchsuchenden DB an. Das sind Dinge, die man noch ändern könnte, falls die Zykluszeit der SPS zu sehr in die Knie geht. Ich bin mal davon ausgegangen, daß du immer ein Telegramm in einen DB schreibst. Mit einem Startoffset könnte man den Beginn der Suche auch noch festlegen, das spare ich mir erstmal :ROFLMAO:.
 
Zuletzt bearbeitet:
Hi Ralle,

danke erst mal für deinen Code. Ich werde ihn in Kürze ausprobieren.
Mit etwas Glück brauch ich ihn aber nicht mehr.

Da sich das empfangen der Daten vom PC über RS232 und Ethernet als sehr aufwändig und vor allem über RS232 als nahezu unmöglich
(nur mit Sondersoftware PC seitig) herausgestellt hat wird es eventuell so sein das unser PC Programmierer eine Sondersoftware erstellt.
Diese soll dann das ganze Datenhandling übernehmen.

Es hängt jetzt natürlich erst mal vom Kunden ab wie er zu dem Vorschlag steht.

Deinen Code werde ich auf jeden Fall ausprobieren.


Nochmals Vielen Dank an alle ...
:p


smartie
 
Zurück
Oben