Step 7 Zahl bestehend aus mehreren Bytes hochzählen

schoch

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

ich tausche gerade mit einer S7-300 (Step7) Daten mit einem SAP System aus.
Der Datenaustausch basiert auf TCP/IP Telegrammen, sprich ich sende und empfange ca. 450 Bytes als Char.
Darunter fallen auch 20 Bytes für eine Sequenznummer, die für das Handshake mit dem SAP System wichtig ist.

Leider muss ich bei bestimmten Situationen aktiv die Sequenznummer eins hochzählen und eine Anfrage ans SAP System senden.

Gibt es hier eine schlanke und einfache Lösung als jedes Bytes separat umzuwandeln und einen Haufen Vergleicher aufzubauen?

Als Beispiel: Die Zahl 199 ist auf Byte 1 "1", Byte 2 "9" und Byte 3 "9" aufgeteilt. Jetzt möchte ich aktiv auf 200 hochzählen, ohne für jedes Byte umzuwandeln und zu vergleichen, da ich 20 Stellen für die Sequenznummer habe.


Vielen Dank im Voraus und viele Grüße

Thomas
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Kostet sicher etwas Gehirnschmalz, aber ich würde denken, in SCL kann man das in einer Schleife machen, wenn man die 20 Bytes in einem Array of Byte stehen hat.

In AWL kann man das auch in einer Schleife machen, Spezialisten machen das vlt. mit Überlauf-Flags, ROL, Schiebebefehlen etc. noch ein wenig trickreicher.

Hatten wir nicht mal einen Programmierwettbewerb im Forum, das wär mal eine Aufgaben dafür. ;-)
 
Die 20 Byte Sequenznummer sind nur ASCII-Ziffern '0' .. '9'?

Man kann das Inkrementieren "zu Fuß" in einer Schleife direkt auf die einzelnen ASCII-Zeichen mit Übertrag programmieren. Dafür braucht man keinen "Haufen Vergleicher". Etwa so:
Code:
text : ARRAY [0..19] OF CHAR; //oder BYTE

FOR i := 19 TO 0 BY -1 DO
  z := (text[i] AND 16#0F) + 1;
  IF z <= 9 THEN
    text[i] := z + '0';
    EXIT;  //kein Übertrag --> fertig
  ELSE
    text[i] := z - 10 + '0';
  END_IF;
END_FOR;

Man könnte auch die hinteren 8 Zeichen der Sequenznummer von ASCII nach DINT konvertieren (z.B. mit STRNG_DI), dann 1 addieren (*) und wieder in ASCII-Zeichenkette zurückverwandeln (DI_STRNG).
(*) sollte bei dem Addieren ein Übertrag bzw. Wert >= 100.000.000 auftreten, dann 100.000.000 abziehen (oder MOD) und nach dem selben Schema 1 auf die 8 Ziffern davor addieren, und ggf auch noch für die ersten 4 Ziffern. Man könnte die Aufgabe/Lösung auch in 3 Blöcke zu je 7 Ziffern aufteilen.

Harald
 
Moin Schoch,

also eine Sequenznummer mit 20 Stellen ist schon ungewöhnlich. Üblicherweise kenne ich 2 Stellen, vielleicht mal 4.

Ich würde mal absprechen, ob die Sequenznummer wirklich 20 Stellen haben muss oder ob 20 Stellen als Platzhalter vorgesehen sind und sie Sequenznummer nur einen geringeren maximalen Wert annehmen kann/soll.

SAP will im Bereich Materialflussrechner Fuß fassen, aber häufig verstehen sie nicht die Problematiken/Anforderungen auf der Steuerungsebene. Dann wundern sie sich, dass wir keinen PC haben und nicht einfach eine 20-stellige Zahl inkrementieren können.

Wenn es denn unbedingt sein muss, kann man die Bytes vielleicht in ein ArrayOfBool übertragen (wandling von ASCII -> Num vorausgesetzt) und dann eine Schleife über das Array laufen lassen. Am LSB starten und dann inkrementieren... Danach wieder in ASCII wandeln.

Bei 20 Zeichen (99_999_999_999_999_999_999) könnte man ~3 Mrd Jahre inkrementieren, wenn jede ms ein Telegramm kommt. Vielleicht ist das die Idee dahinter: es soll sich NIEMALS eine Sequenznummer doppeln? Das wäre echt Unfug.

Bitte noch einmal absprechen! Die Antwort würde mich auch brennend interessieren!

VG

MFreiberger
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn es denn unbedingt sein muss, kann man die Bytes vielleicht in ein ArrayOfBool übertragen (wandling von ASCII -> Num vorausgesetzt) und dann eine Schleife über das Array laufen lassen. Am LSB starten und dann inkrementieren... Danach wieder in ASCII wandeln.
ArrayOfBool? Harald hatte schon in #4 ArrayOfChar bzw. ArrayOfByte vorgeschlagen. Damit ist sein Vorschlag wesentlich näher an der AufgabenStellung:
Ziffer für Ziffer betrachten und abbrechen, sobald kein weiterer Übertrag stattfindet.
Auf BitEbene kann man das natürlich auch tun, mit 4-mal mehr SchleifenDurchläufen. Und ausserdem müsste man 20-fach durch 10 dividieren, um die Ziffern zu erhalten und sie in ASCII zurückwandeln.
 
Mir fällt gerade ein daß man die ASCII-Wandlung gar nicht braucht. Man kann auch gleich direkt mit den ASCII-Ziffern rechnen.
Code:
text : ARRAY [0..19] OF CHAR; //oder BYTE

FOR i := 19 TO 0 BY -1 DO
  c := text[i] + 1;
  IF c <= '9' THEN
    text[i] := c;
    EXIT;  //kein Übertrag --> fertig
  ELSE
    text[i] := '0';
  END_IF;
END_FOR;

Harald
 
Zurück
Oben