Step 7 Schleife mit indirekter Adressierung

Tschigi

Level-2
Beiträge
19
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich habe folgende Aufgabenstellung:

Ich möchte in einem Datenbaustein beliebiger Länge bei einer poitiven Flanke eines Eingangs in jedem ersten Byte eines Doppelwortes das Bit 5 (z.B. DB201.DBX0.5) auf 0 setzen.
Ich habe daher folgendes programmiert:

Zunächst rufe ich den SFC24 auf und speicher die Datenbausteinlänge lokal ab (#DBlength)

Meine Schleife sieht dann wie folgt aus:

U "E 8.4"
FP M 80.5
= L 0.0
U L 0.0
AUF "Status RohstoffM"
L 0
T #Bytenr
ANF: L #Bytenr
SLD 3
LAR1
L 5
+AR1
R DBX [AR1,P#0.0]
L #Bytenr
L 4
+I
L #Bytenr
L #DBlength
>=I
SPB END
SPA ANF
END: NOP 0


Leider kann ich es hier nicht simulieren. Daher habe ich zwei Fragen:

1. Ist das so überhaupt funktionsfähig?
2. Wenn ja, geht die CPU eventuell auf Stop, wenn ich damit einen Datenbaustein mit einer Länge von z.B. 884 Bytes durchratter (zu lange Zykluszeit)?

Für Hilfe wäre ich dankbar
 
Nur als Anmerkung:
Bit 5 wäre in Deinem Beispiel DB201.DBX0.4 und nach L 0.0 fehlt sicher der bedingte Sprung ans Ende (vermutlich beim Posten unter gegangen, oder?).
 
Wenn's so sein soll, ist's ja OK.

Als Alternative zum Rücksetzen des einzelnen Bits wäre z.B. die VerUNDung des DWORDs möglich und man spart sich in jedem Schleifendurchlauf die zusätzliche Bitberechnung des Pointers und damit vermutlich etwas Zeit.
 
Das letzte "L #Bytenr" muss sicher auch eigentlich ein Transfer sein, oder?

Oder davor noch dazwischen, um die neue Bytenummer zu sichern.
 
.
1. Ist das so überhaupt funktionsfähig?
2. Wenn ja, geht die CPU eventuell auf Stop, wenn ich damit einen Datenbaustein mit einer Länge von z.B. 884 Bytes durchratter (zu lange Zykluszeit)?

Für Hilfe wäre ich dankbar

Leider machst du keine Angaben über Anwendung
und eingesetzter CPU.

zu 1.
Nee, ist es so nicht.
Schau dir die Beiträge von hucki und von dtsclipper
an, die geben dir schon mal entscheidende Hinweise.

zu 2.
Wenn du deine Schleife aus 1. dann korrekt am
Laufen hast, kannst du die Zykluszeitüberwachung
je nach deiner eingesetzten CPU noch einstellen.

Auch kannst du die Zeit für den Doppelwort-
Zugriff aus den CPU-Daten entnehmen und
dann einfach mal grob hochrechnen.

Alternativ hast du die Möglichkeit, nur einen
Schleifendurchlauf pro Zyklus bearbeiten zu
lassen.
 
Als Alternative zum Rücksetzen des einzelnen Bits wäre z.B. die VerUNDung des DWORDs möglich und man spart sich in jedem Schleifendurchlauf die zusätzliche Bitberechnung des Pointers und damit vermutlich etwas Zeit.
Dann müßte man zusätzlich das DWORD aus dem DB lesen und spart dadurch eher keine Zeit.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
in jedem ersten Byte eines Doppelwortes das Bit 5 (z.B. DB201.DBX0.5) auf 0 setzen.
[...]
ANF: L #Bytenr
SLD 3
LAR1
L 5
+AR1

R DBX [AR1,P#0.0]
Wenn die Bitnummer nicht variabel vorgebbar sein soll sondern immer Bit .5, dann muß man P#0.5 nicht extra zum AR1 addieren sondern kann das direkt in der indirekten Operation angeben: "R DBX [AR1,P#0.5]"

Wenn Du mehrere hundert Schleifendurchläufe machen willst, dann muß die Schleife effizient programmiert sein.

Harald
 
Stammt Dein Code aus einem FB und sind #DBlength und #Bytenr STAT-Variablen?
Falls das TEMP-Variablen sind oder Du noch andere TEMP-Variablen hast, dann überlappt das L0.0 mit einer TEMP-Variable - nicht gut.

Der Adressvergleich >=I muß genaugenommen >=D heißen, sonst funktioniert Dein Code nur in den ersten 32kB eines DB. Das +I funktioniert zwar, sollte aber ebenfalls ersetzt werden durch +D.

Statt "SPB END + SPA ANF" kann man kürzer schreiben: "SPBN ANF"

Harald
 
Nach dem "U L 0.0" fehlt noch eine Zuweisung. So, wie es jetzt geschrieben ist, bearbeitest Du den Baustein immer und verknüofst den Vergleicher weiter hinten mit L 0.0.
Davon abgesehen, brauchst Du nach dem FP nicht zwangsläufig eine Zuweisung in ein Bit, sondern kannst das Ergebnis direkt weiterverwenden. Eine Zuweisung in ein Bit benötigst Du nur, wenn Du die Flankenauswertung mehrfach verwenden möchtest.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hier mal eine Variante mit speicherindirekter Adressierung, welche ohne AR auskommt:
Code:
IN    IN_WorkDB : INT
TEMP  iWorkDB : INT
      dwMaxAdr : DWORD
      dwAdresse : DWORD


      L     #IN_WorkDB          // Nr des übergebenen DB
      T     #iWorkDB            // in Temp-Int kopieren
      AUF   DB [#iWorkDB]       // den übergebenen DB öffnen
      L     DBLG                // und DB_Länge abfragen
      L     1
      -D
      SPM   END                 // Abbruch: DB ist 0 Byte lang!

      SLD   3                   // DB_Länge - 1 --> höchste Byteadresse P#x.0
      OD    DW#16#7             // entspricht: + P#0.7  (+ Bitadresse .7)
      T     #dwMaxAdr           // --> höchste Bitadresse z.B. P#0.7 bei DB_Länge = 1

      L     P#0.5               // erste zu beschreibende Adresse im DB (DBX0.5)
LOOP: T     #dwAdresse          // im Schleifenzähler (Pointer) merken
      L     #dwMaxAdr           // höchstmögliche DBX-Bitadresse
      >D                        // Pointer ist größer? 
      SPB   END                 // ja -> fertig/Abbruch / nein -> SET VKE für R

      R     DBX [#dwAdresse]    // rücksetzen DBX0.5 / DBX4.5 / DBX8.5 ...

      L     #dwAdresse
      +     L#32                // + P#4.0 Offset zur nächsten Adresse
      SPA   LOOP                // --> wiederholen mit P#4.5 / P#8.5 / P#12.5 ...

END:  SET
Ich würde den Code in einen eigenen FC packen und die Flankenerkennung außerhalb dieses FC machen und den FC nur aufrufen, wenn er die Bits löschen soll.
Unschön ist noch die Übergabe der DB-Nummer als INT, weil dadurch die DB-Nummer nicht in den Referenzdaten erscheint. Wenn die DB-Nummer variabel sein soll, dann geht es aber leider nicht anders.

Harald
 
Hallo an alle,

vielen Dank für die Hinweise und Tipps. Hat mir alles sehr weitergeholfen.

Tolle Sache, dass einem hier so schnell geholfen wird.

:D:D:D:D:D:D
 
Zurück
Oben