String: Übergabe der Max Länge Falsch

kai86

Level-1
Beiträge
158
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
ich Habe eine Funktion in die folgendermaßen aussieht.
Bei DCI_GetStringParam() wird nun eine ID als Input und die Var2 und Var3 als Output übergeben.
Code:
FUNCTION Command:Void
VAR_TEMP
    Var1 : DINT;
    Var2 : STRING[16];
    Var3 : STRING[16];
END_VAR

Var1 := DCI_GetDIntParam(101);
DCI_GetStringParam(id:=100,s:=Var2);
DCI_GetStringParam(id:=102,s:=Var3);

END_FUNCTION

Ich zerlege nun den String und bekomme bei s_max 132 statt 16 raus und kann mir das nicht erklären. Habe auch schon als IN_Out deklariert, aber da kommt das selbe. Hat einer eine Idee woran das liegt das der max nicht richtig übergeben wird?

Code:
FUNCTION DCI_GetStringParam: VOID
VAR_INPUT
    id:DWord;
END_VAR
VAR_OUTPUT
    s:STRING;
    S_REF AT s: STRUCT
        s_max:BYTE;
        s_act:BYTE;
        s_chars:ARRAY[1..254] OF BYTE;
    END_STRUCT;
END_VAR
VAR_TEMP
    size:INT;
    max_size:INT;
    pos:INT;
END_VAR
DCI_SeekByParamID(rid:=id,rtyp:=9);
max_size:=BYTE_TO_INT(S_REF.s_max);
size := DINT_TO_INT(DCP_ReadDInt());
IF size>max_size THEN
    DCP_Seek(size);
    S_REF.s_act:=0; 
ELSE
    FOR pos:=1 TO size DO
       S_REF.s_chars[pos]:=DCP_ReadByte(); 
    END_FOR;
    S_REF.s_act:=INT_TO_BYTE(size); 
END_IF;
END_FUNCTION
 
Hallo,
woher kommen denn die Eingangs-Strings der Funktion "Command" ?
Sind die Strings korrekt initialisiert ? Die Header-Bytes stehen da nur korrekt drin, wenn du sie auch (beim Initialisieren bzw. Zuweisen) korrekt hineingeschrieben hast ...

Gruß
LL
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Es gibt keine Eingangsstrings bei Command ich erstelle die da als Temp Vars und übergebe die der GetStringParam als Outputparameter. Diese maskiert die dann und kann dann lesend auf die max_länge zugreifen. Diese habe ich bei Command als 16 definiert wie man sieht. und diese 16 will ich auch in der funktion getstringparam wieder auslesen.
 
... entschuldigung ... beim hinsehen habe ich bei der "Command" die Variablen irgendwie als INPUT-Var's gesehen. Das mit dem TEMP hatte ich gar nicht registriert - ändert aber gar nichts an meiner Aussage.
In dem Script von Command sind die Strings NICHT initialisiert - d.h. das steht irgendein Speicher-Müll drin. Die blosse Deklaration bewirkt gar nichts. Du mußt als mindestens das rot markierte noch einfügen ...
Code:
FUNCTION Command:Void
VAR_TEMP
    Var1 : DINT;
    Var2 : STRING[16];
    Var3 : STRING[16];
END_VAR

[B][COLOR=red]Var2 := '' ;[/COLOR][/B]
[B][COLOR=red]Var3 := '' ;[/COLOR][/B]

Var1 := DCI_GetDIntParam(101);
DCI_GetStringParam(id:=100,s:=Var2);
DCI_GetStringParam(id:=102,s:=Var3);

END_FUNCTION
... dann sollte es funktionieren ...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ok damit gehts :p, aber wenn ich den string nun in Command übergebe ändert sich der aktwert des string auf 16. warum das??? in der funktion getstringparam ist noch alles ok akt ist in dem fall 9 und max ist 16. nun wird er in einen string in einem Datenbaustein kopiert, darin steht dann beides mit 16 drin.

kann es sein das er den max wert als neuen aktwert übernimmt? wenn ja warum macht der so ein blödsinn?
 
Zuletzt bearbeitet:
Im Prinzip wird ein Commando, welches in einem Buffer steht ausgewertet(wurde über ethernet darein gelesen) und die darin befindlichen parameter werden in einen Datenbaustein geschrieben.

mein problem ist nur das folgende.

DATA.LocationID := Var3;

bei diesem aufruf macht der mist.

aus max_size(Var3)=16 macht der natürlich das max_size(LocationID)=254
aber aus act_size(Var3)=9 macht der in den meisten fällen 16 und das darf der nicht der muss doch die 9 übernehmen oder etwa nicht?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
:confused: ... tut mir leid ... vielleicht ist heute nicht mein tag ... aber ich habe nichts verstanden ...
Also nochmal : was möchtest du genau machen (von Anfang an) ? Was ist der Sinn von "DCI_GetStringParam" ?
 
vielleicht habe ich es auch dumm erklärt.
Eigentlich ist alles gerade unwichtig für dich.
Ich will nur einen String kopieren.

DataBlock.String1 := String2

Vor dem Copy:
Struktur String1 :
Byte0 : 16 //Max_Size
Byte1 : 0 //Aktuelle_Size
Byte2 : 0
Byte3 : 0

Struktur String2 :
Byte0 : 16
Byte1 : 2
Byte2 : 41
Byte3 : 42

Nach dem Copy:

Struktur String1 :
Byte0 : 16 //Max_Size
Byte1 : 16 //Aktuelle_Size
Byte2 : 41
Byte3 : 42

mein wunsch ist aber das in Byte1 2 steht weil das logisch ist ^^
 
... ist nicht so ganz einfach zu helfen, wenn man das Ziel nicht so richtig verstanden hat.
Aber egal - mal einfach ein paar grundsätzliche Dinge dazu :

- Zunächst würde ich mich mal von den TEMP-Variablen lösen. Da kannst du später wieder hin, wenn die Grundlage läuft - im Augenblick nimmst du dir so die Chance des debuggen.
- Strings sind nach ihre Deklaration erstmal speichertechnisch nichts. Nur wenn du z.B. in einem DB einen String anlegst und ihn dort per Vorbelegung auch schon zuweist dann ist der Header korrekt. Das Gleiche tut auch SCL wenn du schreibst : "myString := '1234' ;". Ohne das ... ???
- eine wie auch immer geartete COPY-Funktion ändert daran auch nichts.
- Ist der String nicht korrekt initialisiert so funktionieren die entsprechenden Routinen wie z.B. LEFT, RIGHT, MID usw. aus der Siemens-Bibliothek erst gar nicht.

So ... jetzt bist du erst wieder dran ...

Gruß
LL
 
Zuviel Werbung?
-> Hier kostenlos registrieren
also der string ist 100% richtig initializiert Var := ''; habe ich gemacht dann kommt auch der Stringheader richtig rüber. wenn ich nun aber die Var in einen String in nem DB kopieren will macht der den Header völlig kaputt.
 
Ich weiß das Var3 den richtigen Header hat weil ich den string mit ner maske zerlege, aber er wird nicht korekt in DATA.LocationID angezeigt.

Code:
FUNCTION DCI_HandleCommand:Void
VAR
    Var1 : DINT;
    Var2 : STRING[16];
    Var3 : STRING[16];
    S_REF AT Var3: STRUCT
        s_max:BYTE;
        s_act:BYTE;
        s_chars:ARRAY[1..16] OF BYTE;
    END_STRUCT;
END_VAR
Var2 := '';
Var3 := '';

IF DCI_Command.MessageID=501 THEN
    DCI_COMMAND.handled := True;    
    //read all parameters
    Var1 := DCI_GetDIntParam(101);
    DCI_GetStringParam(id:=100,s:=Var2);
    DCI_GetStringParam(id:=102,s:=Var3);
    //if the message is valid, use them
    IF DCI_Command.isOK THEN  
        DATA.PortID     := Var1;
        DATA.MaterialID := Var2;
        DATA.LocationID := Var3;
    END_IF;
    User_Config.size     := BYTE_TO_INT(S_REF.s_act);
    User_Config.max_size := BYTE_TO_INT(S_REF.s_max);
END_IF;

END_FUNCTION
 
Zuviel Werbung?
-> Hier kostenlos registrieren
ich nehme mal an, dass dein String von "GetStringParam" von dieser Sequenz kommt :
Code:
IF size>max_size THEN
    DCP_Seek(size);
    S_REF.s_act:=0; 
ELSE
    FOR pos:=1 TO size DO
       S_REF.s_chars[pos]:=DCP_ReadByte(); 
    END_FOR;
    S_REF.s_act:=INT_TO_BYTE(size); 
END_IF;
was macht DCP_Seek und vor Allem, was macht DCP_ReadByte ?

Ergänzung:
was macht außerdem "DCI_SeekByParamID" ? Wie hängt das alles zusammen ?
 
Zuletzt bearbeitet:
DCP_Seek() überspringt den speicherbereich wo der string ist, falls der String größer ist als das max.

DCP_ReadByte ließt den Buffer Byte für Byte aus und schreibt alles in den string
 
lass dir nicht alles einzeln aus der Nase ziehen ...
Welcher Puffer wird ausgelesen und woher weiß "DCP_ReadByte" welches Element es wann liefern soll.
Es wäre schon hilfreich, das ganze Konstrukt zu kennen. Ich vermute mittlerweile den Fehler / das Problem in der Interaktion der einzelnen Funktionen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
dachte ehr das das unwichtig sei aber ok.
also ich bekommen von nem pc daten über TCP rein diese werden dann in einen Empfangspuffer geschrieben. Danach wird der gleich ausgewertet.
So eine nachricht besteht aus nem Header und mehreren Variablen.
DCI_SeekByParamID überprüft, wo die gesuchte Variable im string steht.

brauchst du noch infos?
 
Code:
FUNCTION DCP_ReadByte: BYTE
    DCP_ReadByte := buff.data[ buff.buffers[buff.current_buffer].start + buff.buffers[buff.current_buffer].pos ];
    DCP_Seek(delta:=1);
END_FUNCTION

Code:
DATA_BLOCK BUFF
    // buffer(s) for sending and receiving of messages
    STRUCT
        sourceID        : INT   := 0;
        destinationID   : INT   := 0;
        packageID       : INT   := 0;
        messageID       : DWORD := DW#16#0;
        param_count     : INT   := 0;
        seekError       : BOOL  :=false;
        
        current_buffer:INT:=0;
        
        msg_lost_bOverflow    : INT:= 0;
        event_lost_bOverflow  : INT := 0;
        alarm_lost_bOverflow  : INT := 0;
        
        buffers: ARRAY [0..4] OF STRUCT
            start: INT:=-1;
            size: INT:=-1;
            pos: INT:=0;     //cursor for read/write operations
            msg_pos: INT:=0; //start of the current message
            tcp_pos: INT:=0;
        END_STRUCT;
        TYPE_SIZES: ARRAY[1..10] OF INT;
        data: ARRAY [0..20000] OF BYTE;
    END_STRUCT
BEGIN
END_DATA_BLOCK
 
Zurück
Oben