Step 7 Pointer Beckhoff Übersetzung

danny_v1

Level-2
Beiträge
8
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo habe ein Problem ein Progamm von Beckhoff (ST) in Step7(SCL) zu übersetzen.

Speziell wenn es um Pointer geht.
Ein Codeausschnitt von Beckhoff sieht zB folgendermaßen aus:

Code:
FUNCTION FCxxx : STRING(80)
 VAR_INPUT     
     pStringInput: POINTER TO STRING(10000); 
END_VAR 
VAR
     ppStringVar : POINTER TO BYTE; 
END_VAR

   ppStringVar := ADR(pStringInput^);  

... 
FCxxx := '';  
END_FUNCTION

Wie kann man das in SCL umssetzen.

Hoffe mir kann da jemand auf die Sprünge helfen.
 
Wie kann man das in SCL umssetzen.
Gar nicht.
- es gibt keine Pointer-Variablen
- es gibt keine ADR-Operatoren und keine Pointer-Dereferenzierung
- es gibt keine STRING(10000)

Man kann höchstens höchst aufwändig etwas mit ANY-Pointern basteln, doch da geht die ganze Datentyp-Kontrolle verloren und es gibt bestimmt einfachere Lösungen.
Da mußt Du Dir einen anderen Algorithmus einfallen lassen, der das gleiche Ergebnis wie der Beckhoff-Code liefert.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke für die schnelle, aber ernüchternde Antwort.

Gut anstatt STRING(10000) könnte man auch ein ARRAY[0..10000] OF CHAR verwenden.

Wie könnte denn der Algorithmus aussehen. Könnte ja auch ein Baustein in AWL sein der dann das gewünschte Ergebnis liefert.
 
Das ist ein Teil einer Funktion, welche String Befehle einer externen Schnittstelle auswertet und prüft ob ein glültiger Befehl angekommen ist.

Ich kann leider nicht viel größere Codeteile posten.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Die Frage ist, brauchst du wirklich unbedingt 1000 Byte.
Für Strings (max. 255 Byte bei S7), gibt es recht gute Funktionen in der Standard-Library von Siemens. (find, concat, mid, usw.)
Evtl. könnte man den Input in mehrere Strings aufteilen.
Wenn nicht:
Hast du ein Array, ist die Frage, nach was ist im Array zu suchen, gibt es eine festgelegte Syntax, gibt es Texttrenner zwischen Befehlen etc.
Ist das so, könnte man zuerst das Array nach dem ersten Buchstaben eines Befehls durchsuchen, hat man einen gefunden, nimmt man den 2., 3. usw. Buchstaben und vergleicht den mit der zu suchenden Befehlsfolge.
Aber genaues kann man erst sagen, wenn man mehr weiß.
So eine ähnliche (rel. einfache) Suchroutine hatten wir hier schon einmal, aber das ist locker 8-9 Jahre her und ob ich das noch finde???
 
In mehrere Strings aufteilen ist wieder so eine Sache, da hat man ja wieder für jeden String einen Header.
Die Befehle haben Trennzeichen, dadurch sollte das mit dem Array of Char eigentlich schon funktionieren. Und da eine Suchfunktion zu bauen sollte nicht das große Problem darstellen.
Die Sache mit den Pointer stellt erstmal noch das größere Problem dar.
 
Um auf die einzelnen Elemente (Zeichen) eines Array of Char zuzugreifen braucht man keine Pointer. Man kann die Elemente auch indiziert ansprechen. Pointer sieht vielleicht intelligenter aus, indizierter Zugriff wird andererseits von jedem Programmierer "sofort" verstanden.

Eine Pointer-Lösung für Zugriff auf ein Array kann man in eine Index-Lösung umformen und umgekehrt. Bei Index-Lösungen kann der Compiler überwachen, daß nicht auf Speicher außerhalb des Arrays zugegriffen wird. Bei Pointer-Lösungen kommt die Notbremse erst zur Laufzeit, wenn schon quer durch fremden Speicher gelesen/geschrieben wurde bis endlich auf eine nicht vorhandene oder unzulässige Adresse zugegriffen wird.

Wenn Du etwas mehr von dem Code zeigen würdest, dann könnte man konkreter antworten. Hier mal ein allgemeines Beispiel:

Mit Pointer (funktioniert Hardware-abhängig, in SCL nicht möglich):
Code:
ppCharBuf := ADR(inputCharBuffer^);
FOR index := 0 TO 999 DO
  IF ppCharBuf^ = 'A' THEN  //Zeichen 'A' gefunden
    ... ;
  END_IF;
  ppCharBuf := ppCharBuf + 1;  //Pointer auf nächstes Array-Element setzen
END_FOR;
Ohne Pointer (funktioniert in jedem ST und SCL):
Code:
FOR index := 0 TO 999 DO
  IF inputCharBuffer[index] = 'A' THEN  //Zeichen 'A' gefunden
    ... ;
  END_IF;
END_FOR;

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Vielen Dank für das Beispiel, hab es jetzt auch erstmal so umgesetzt

Code:
FUNCTION FINDCHAR: VOID

VAR_INPUT
    ENABLE          : BOOL;
    IN_ARRAY        : ARRAY [0..999]OF CHAR;
    IN_FIND         : ARRAY [0..79] OF CHAR;
    IN_FIND_ENDCHAR : CHAR;
END_VAR

VAR
    INDEX_IN_ARRAY  : INT;
    INDEX_IN_FIND   : INT;
    
END_VAR

VAR_OUTPUT
  POSITION        : INT;
END_VAR
  

BEGIN

        FOR INDEX_IN_ARRAY:= 0 TO 999 DO
             IF INDEX_IN_FIND< 80 THEN
                
                IF IN_FIND[INDEX_IN_FIND]=IN_FIND_ENDCHAR THEN
                    POSITION:=POSITION;
                    EXIT;
                END_IF;
                     
                  IF IN_ARRAY[INDEX_IN_ARRAY] = IN_FIND[INDEX_IN_FIND] THEN
                        
                        IF POSITION=0 THEN
                            POSITION:=INDEX_IN_ARRAY+1;
                        END_IF;

                        INDEX_IN_FIND:=INDEX_IN_FIND+1;
                  
                  ELSIF IN_ARRAY[INDEX_IN_ARRAY] <> IN_FIND[INDEX_IN_FIND] THEN
                      POSITION:=0;
                      IF INDEX_IN_FIND>0 THEN
                        INDEX_IN_FIND:=0;
                      END_IF;
                  END_IF;
                    
              END_IF;  
        END_FOR;

IF ENABLE=TRUE THEN
    INDEX_IN_ARRAY:=0;
    INDEX_IN_FIND:=0;
END_IF;
END_FUNCTION

Es funktioniert so auch erstmal ganz gut
 
Es funktioniert so auch erstmal ganz gut
Das täuscht gewaltig. :cool:

Was mir auf die Schnelle auffällt:
  • VAR in FUNCTION ist VAR_TEMP! Du liest INDEX_IN_FIND ohne vorher was reinzuschreiben - der Inhalt ist unbestimmt, quasi zufällig
  • OUTPUT rücklesen ist Pfui. OUTPUT mehrmals beschreiben ist ganz großes Pfui. Das kann in Multitasking-Prozessen oder in Verbindung mit HMI Probleme machen.
    Benutze für POSITION eine TEMP-Variable und kopiere erst am Ende auf den OUTPUT
  • was soll so eine Operation: "POSITION:=POSITION;" ?
  • realisiere die FUNCTION besser als FUNCTION_BLOCK und übergebe die Arrays an IN_OUT --> das übergibt nur einen Pointer auf die Arrays anstatt die Arrays zu kopieren (außer S7-1200/1500, da kenne ich mich nicht so aus, da könnte es sein, daß trotzdem eine Kopie des Arrays übergeben wird)

Harald
 
Zurück
Oben