Step 7 32-Bit Unsinged-Int in String wandeln

fabries

Level-1
Beiträge
9
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Bekomme von einer Siemens-Software Werte die im 32-Bit-Unsigned-Int-Format gelesen werden müssen. Diese aber werden als DWORD in einem DB gespeichert.
Meine Aufgabe ist es jetzt den 32-Bit Unsigned-Int-Wert in dem DWORD als String darzustellen. Probelm ist, dass S7 nur mit DINT vorzeichenbehaftete INT-Werte darstellen kann, sprich +/- 2^31! Ich benötige aber 0 bis 2^32!

Hoffe, dass jemand mir mit dem Problem helfen kann!?

Über Lösungsvorschläge wäre ich nicht abgeneigt.
 
Theoretisch muß man bei "negativen" Werten "einfach nur" 2^32 (4.294.967.296) addieren, was mit 32-Bit-Operationen allerdings nicht geht ... :(
Man kann die 2^32-Addition aber in Teilschritte zerlegen. :)
Ich hätte da folgende Idee

Algorithmus:
* ist der Ausgangswert negativ, dann 294.967.296 addieren (294.967.296 = 2^32 - 4*10^9)
* den Wert nun durch 1.000.000.000 dividieren (10^9)
* der Divisionsrest ergibt die letzten 1 bis 9 Ziffern des Wertes (--> DI_STRNG nutzbar)
* der Quotient ergibt die 10^9-Ziffer des Wertes - war der Ausgangswert negativ, dann zuvor 4 dazuaddieren

Pseudocode mit 32-Bit-Ganzzahloperationen:
#udint_In sei der Ausgangswert (32-Bit unsigned DINT)
die weiteren Variablen mit #.. können TEMP sein ( #x.. BOOL, #di.. DINT, #s.. STRING )
Code:
#xNegativ := #udint_In < 0    //signed DINT-Vergleich (oder Bit .31 testen, z.B. mit SLD)

#diTemp := #udint_In 
IF #xNegativ THEN #diTemp := #diTemp + 294967296

#diZ1 := #diTemp / 1000000000
IF #xNegativ THEN #diZ1 := #diZ1 + 4
#sZ1 := ""
IF #diZ1 > 0 THEN #sZ1 := DI_STRNG(#diZ1)

#diRest := #diTemp MOD 1000000000
#sRest := DI_STRNG(#diRest)

#sErgebnis_Out := CONCAT(#sZ1,#sRest)
Ich würde wahrscheinlich nicht DI_STRNG und CONCAT benutzen, sondern den String per fortlaufender Division mit 10 selber erzeugen (irgendwie war da noch ein Problem mit führendem Vorzeichen/Leerzeichen bei DI_STRNG), es liest sich hier im Beispielcode aber besser.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Harald,

viel Dank für dein Lösungsvorschlag! Eines ist mir noch nicht ganz klar!

Warum bei ... ("der Quotient ergibt die 10^9-Ziffer des Wertes - war der Ausgangswert negativ, dann zuvor 4 dazuaddieren") 4 addieren?
und bei
(IF #xNegativ THEN #diTemp := #diTemp + 294967296) -> Wie kommst du auf 294967296? ...wäre genau (2^32)-(4*10^9)


gibt es auch eine Möglichkeit aus einem String[10] eine 32-Bit unsigned-Int zu wandeln?

-fabries
 
Warum bei ... ("der Quotient ergibt die 10^9-Ziffer des Wertes - war der Ausgangswert negativ, dann zuvor 4 dazuaddieren") 4 addieren?
und bei
(IF #xNegativ THEN #diTemp := #diTemp + 294967296) -> Wie kommst du auf 294967296? ...wäre genau (2^32)-(4*10^9)
Das Problem ist, daß man in S7-AWL oder S7-SCL die 32-Bit-unsigned-Wandlung mit 32-Bit-signed-Operationen durchführen muß. Daher meine Idee, die Wandlung auf eine 31-Bit-unsigned-Wandlung zu reduzieren (ergibt dann immer positive Werte!) und für die höchstwertige Ziffer eine Sonderbehandlung zu machen.

Nochmal:
Theoretisch muß man bei "negativen" Werten "einfach nur" 2^32 (4.294.967.296) addieren, was mit 32-Bit-Operationen allerdings nicht geht ... :(
Man kann die 2^32-Addition aber in Teilschritte zerlegen. :)
Wenn der Ausgangswert im "negativen" Bereich DW#16#80000000 bis DW#16#FFFFFFFF liegt (unsigned Ansicht: 2.147.483.648 bis 4.294.967.295, signed Ansicht: -2.147.483.648 bis -1), dann werden in meinem Algorithmus 294.967.296 (2^32 - 4*10^9) addiert und bei der per Division mit 10^9 abgespaltenen höchstwertigen Ziffer die 4 addiert (entspricht den 4*10^9). Insgesamt entspricht das der Addition von 2^32 (4.294.967.296).

Oder praktisch gesehen:
Bei den positiven Werten 0 bis 2.147.483.647 ergibt die signed-Division mit 10^9 die Werte 0, +1 oder +2.
Bei den "negativen" Werten 2.147.483.648 bis 4.294.967.295 (-2.147.483.648 bis -1) ergibt die signed-Division mit 10^9 die Werte -2, -1 oder 0, was dann durch Addition der 4 zu +2, +3 oder +4 korrigiert wird.


gibt es auch eine Möglichkeit aus einem String[10] eine 32-Bit unsigned-Int zu wandeln?
Das würde ich nach dem gleichen Prinzip (nur "rückwärts") machen: die letzten 9 Ziffern des String normal in DINT wandeln und dann die Sonderbehandlung der ersten Ziffer: 0, 1, 2, 3 oder 4 * 10^9 addieren und wenn dabei ein "negativer" Wert rauskommt, dann muß wahrscheinlich noch ein Korrekturwert (?) addiert werden - doch das läßt sich recht einfach ausprobieren (simulieren).


Ich muß noch erwähnen, daß mein vorgeschlagener Algorithmus nur eine ungetestete Idee/Theorie ist - es müsste aber tatsächlich so funktionieren.

Vielleicht gibt es für Deine Wandlungen auch schon fertige Bausteine, z.B. OSCAT, ...?

Harald
 
Zurück
Oben