Step 7 Abfrage eines Fehlerdatenbausteines mittels eines Funktionsbausteines

DDuesentrieb

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

ich habe schon fleißig die Suchfunktion bemüht. Dabei habe ich auch die Funktion von Loop und Pointer entdeckt.
Mit Hilfe dieser wollte ich mir jetzt eine Schleife basteln, welche die im Baustein angelegten Word - Variablen auf 0 prüft.
Dies soll dazu dienen um für das spätere Programm eine Sammelstörmeldung zu erzeugen.
Hier für benütze ich folgenden Code:

Code:
      L     #DB_Nr
      T     #Aux_DB_Nr

      AUF   DB [#Aux_DB_Nr]
      L     DBLG
      T     #Length_DB

      L     #Length_DB // hier möchte ich die richtige Länge für meine Loop Schleife erzeugen
      L     2
      -I    
      L     2
      /I    
      T     #Length_DB


      L     #Length_DB
Next: T     #Loop_Count

      L     #Loop_Count
      L     2
      *I    
      SLD   3
      LAR1  
      L     DBW [AR1,P#0.0]
      L     W#16#0
      <>I   
      =     #Collecting_Disturbance

      LOOP  Next

Sobald ich diesen in die CPU lade und ausführe bekomme ich die im beigefügten Bild angezeigte Fehlermeldung.


Fehlermeldung.JPG


Wenn ich vom Diagnosepuffer zum Baustein springe, springt er an die Stelle, wo über den Pointer das Datenwort geladen wird.


Könnt ihr mir weiter helfen, wo hier der Fehler liegt? Ich bin mit meinem Latein etwas am Ende :confused:

Grüße Daniel
 
Zuletzt bearbeitet:
[EDIT]falsche Antwort[/EDIT]

ändere
Code:
 *I
in
Code:
 +I

[EDIT] wie Ralle im Folgenden richtig bemerkt, ist das nicht des Pudels Kern [/EDIT]
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Vielen Dank für die schnelle Antwort daran hat es gelegen!

Jetzt bekomme ich nur eine Zyklus Überschreitung. Der Loop wird 26 mal ausgeführt.
Ist das schon zu viel?
 
@4L
Deinen Vorschlag (+I statt *I) halte ich für falsch, er will ja das DW adressieren.
Bei Länge des DB von 22 steht in seinem LoopCount eine 10.
Also muß er diesen auch wieder mit 2 multiplizieren, um auf die richtige Adresse zu kommen oder übersehe ich etwas?
26 Schleifen sollte die SPS locker machen oder sie ist mit der Zykluszeit auch ohne deinen Code schon an der oberen Grenze angelangt.

= #Collecting_Disturbance

geht nicht, du würdest das letzte Ergebnis, bevor du aus der Loop dringst erhalten. Also besser

S #Collecting_Disturbance

und dann vor der Loop Rücksetzen.

Hier mal ein kleines Code-Beispiel, ist schon älter, wird aber nie angefasst, da es so läuft, Länge ist hier fest, kann man ja variabel machen…
Da wird eine Variable hochgezählt für die Anzahl der DW, die <> 0 sind, aber man könnte auch gleich ein S Merker x.y nutzen.

Code:
      AUF   "STOERMELDUNGEN DB"


      L     P#0.0
      T     #pointer_1


      L     0
      T     #result


      L     64                          //count of messages 
SC02: T     #INTcounter


      L     DBW [#pointer_1]            // load word
      L     0                           // load 0
      ==I                               // no errormessage !!!
      SPB   NUL2
      L     #result
      L     1
      +I    
      T     #result


NUL2: NOP   0                           // pointer +1 next WORD
      L     #pointer_1
      L     P#2.0
      +D    
      T     #pointer_1
      L     #INTcounter
      LOOP  SC02


      L     #result
      L     0
      <>I   
      =     "M1.0 main error"
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
@4L
Deinen Vorschlag (+I statt *I) halte ich für falsch, er will ja das DW adressieren.
Bei Länge des DB von 22 steht in seinem LoopCount eine 10.
Also muß er diesen auch wieder mit 2 multiplizieren, um auf die richtige Adresse zu kommen oder übersehe ich etwas?

ich gebe zu, dass das durchaus ein Problem sein könnte ...
lange nicht mehr gepointert ;o)

also ja: die Adresse berechnet sich mit 2*Loop_Count

das Problem hier war ja offensichtlich auch ein anderes... die nicht funktionierende Schleife
 
Vielen Dank für eure schnellen und hilfreichen Antworten! :idea:

@Ralle

Danke für dein Code - Beispiel, dass werde ich mir jetzt mal anschauen

Grüße

Daniel
 
Vielen Dank für eure schnellen und hilfreichen Antworten! :idea:

@Ralle

Danke für dein Code - Beispiel, dass werde ich mir jetzt mal anschauen

Grüße

Daniel

Sollte auch mit deinem Code gehen, wenn du den letzen Post von 4L berücksichtigst.
Bei mir ist der ind. Zugriff anders geschrieben, aber man kann beides nutzen.
#pointer_1 ist ein DWORD
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hier nochmal mein kompletter Code, falls jemand auf das Thema stößt.
Hab die Abfrage von dem Datenwort 0 noch von Hand eingefügt, da dieses durch den Loop nicht
durchlaufen wird.

Code:
      L     #DB_Nr
      T     #Aux_DB_Nr

      AUF   DB [#Aux_DB_Nr]
      L     DBLG
      T     #Length_DB

      L     #Length_DB
      L     2
      -I    
      L     2
      /I    
      T     #Length_DB


      CLR   
      =     #Collecting_Disturbance

      L     #Length_DB
Next: T     #Loop_Count

      L     #Loop_Count
      L     2
      *I    
      SLD   3
      LAR1  
      L     DBW [AR1,P#0.0]
      L     W#16#0
      <>I   
      S     #Collecting_Disturbance

      L     #Loop_Count
      LOOP  Next


      L     DBW    0
      L     W#16#0
      <>I   
      S     #Collecting_Disturbance
 
Ok dann muss ich mir das nochmal anschauen. Es war nur der Fall, dass es mir das Datenwort 0 nicht ausgewertet hat.
Aber dann probiere ich des gleich nochmal aus!

[Edit]
Habe es jetzt nochmal ausprobiert bei meinem Code scheint es so zu sein, dass das Datenwort 0 nicht abgefragt wird.
Warum auch immer :/
[/Edit]
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
echt nicht mein Tag heut oder einfach zu lange raus aus der Materie

Code:
*
      AUF   DB [#Aux_DB_Nr]
      L     DBLG
      L     2
      /I    
next: T     #Loop_Count
      +     -1
      SLD   4
      LAR1  
      L     DBW [AR1,P#0.0]
      L     0
      <>I   
      S     #Collecting_Disturbance
      L     #Loop_Count
      LOOP  next
 
Zuletzt bearbeitet:
Es wird keinen Schleifendurchlauf geben, bei dem #Loop_Count = 0 ist (außer der DB ist zufällig nur 2 Byte lang).
Die Verwendung von LOOP ist vielleicht nicht ganz glücklich gewählt. Man könnte auch vor der Schleife die höchste mögliche Wordadresse berechnen und in der Schleife nur vergleichen, ob die aktuelle Wordadresse größer ist. Dann am besten statt #Loop_Count gleich die Wordadresse als Schleifenindex benutzen (immer nur um P#2.0 erhöhen und für den nächsten Schleifendurchlauf speichern). Das bringt mich dann auf die Idee, auf AR1 zu verzichten und stattdessen direkt speicherindirekte Adressierung zu verwenden ( L DBW [#Word_Address] ).

@Mr.XX
Vielleicht solltest Du mal erklären, warum Du von DBLG 2 abziehst.
Enthält Dein DB nicht eigentlich nichts weiter als das Fehlerbit-Array?

Eine Prüfung, ob das Öffnen des übergebenen DB #DB_Nr (*) erfolgreich war, wäre sinnvoll.
(*) was in den Referenzdaten noch nichtmal zu finden sein wird

Im übrigen könntest Du die Schleife auch schon abbrechen, sobald Du ein Word <> 0 gefunden hast.

Wenn man Schleifen programmiert, dann sollte man die Schleifen möglichst effizient programmieren und z.B. alle unnötigen (konstanten) Berechnungen aus der Schleife herausnehmen. Es gibt aber bekanntlich viele Wege nach Rom, und viele Geschmäcker und Vorlieben.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@PN/DP

Der Datenbaustein ist nur für die Fehlermeldungen reserviert. Die 2 hab ich von der Gesamtlänge abezogen, da die Länge von meinem Datenbaustein 52 ist.
Das letzte Datenwort aber die Adresse 50 hat.

Grüße
 
DBLG = 52 Byte = 26 Word
Wenn Du 2 abziehst, dann wird Deine Schleife nur 25 mal durchlaufen und je nach Programmierung wird entweder das DBW50 oder das DBW0 nicht ausgewertet. Das ist wohl kaum das, was Du wolltest.

Harald
 
Zurück
Oben