Step 7 Variable datenlänge empfangen mit Fb64

RMLIF

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

Ich muss mit dem FB 64 TRCV_TCP eine Variable datenlänge empfangen die aber nie mehr als 64 Bytes beträgt dazu hab ich mir den baustein in scl so aufgerufen

Code:
// Aufruft TResive Bausteine
 
     Recive(EN_R :=Recive_Start  // IN: BOOL
                   ,ID :=TCP_Verbindung  // IN: WORD
                   ,LEN :=0  // IN: INT
                   ,DATA :=at_str_Recive.chars  // INOUT: ANY
                   ); 
      Recive_NDR := Recive.NDR; // OUT: BOOL
      Recive_Busy := Recive.BUSY; // OUT: BOOL
      Recive_Error := Recive.ERROR; // OUT: BOOL
      Recive_Status:= Recive.STATUS; // OUT: WORD
      Recive_LEN:= Recive.RCVD_LEN; // OUT: INT

    at_str_Recive.max_length :=64;  
    at_str_Recive.act_length :=64;

    IF Recive_NDR  THEN
           HM_Ablauf.Recive_Daten_Empfangen:=true;          
                END_IF;
    IF Recive_Error THEN
           HM_Ablauf.Recive_Daten_Error:=true;          
                END_IF;
Diese Variante hab ich auch schon versuch wo ich bei LEN eine Feste Länge eingetragen habe auch ohne erfolg
Code:
  Recive(EN_R :=Recive_Start  // IN: BOOL
                   ,ID :=TCP_Verbindung  // IN: WORD
                   ,LEN :=64  // IN: INT
                   ,DATA :=at_str_Recive.chars  // INOUT: ANY
                   ); 
      Recive_NDR := Recive.NDR; // OUT: BOOL
      Recive_Busy := Recive.BUSY; // OUT: BOOL
      Recive_Error := Recive.ERROR; // OUT: BOOL
      Recive_Status:= Recive.STATUS; // OUT: WORD
      Recive_LEN:= Recive.RCVD_LEN; // OUT: INT

    at_str_Recive.max_length :=64;  
    at_str_Recive.act_length :=64;

    IF Recive_NDR  THEN
           HM_Ablauf.Recive_Daten_Empfangen:=true;          
                END_IF;
    IF Recive_Error THEN
           HM_Ablauf.Recive_Daten_Error:=true;          
                END_IF;

jetzt hab ich nur das problemm das mir Recive_NDR nie True wird und ich keine Daten empfange
muss ich da was anders machen oder geht das mit TRCV so nicht
Welchen Baustein müsste ich dann verwenden

Grüße Rudi
 
Zuletzt bearbeitet:
Wenn ich richtig erinnere hängt das von der SPS ab, (Firmwarestand vielleicht???, neuere Siemens-SPS sollten das können) ob man für Len "0" angeben kann und dann ein Datenpaket empfangen kann, das variable Länge hat.
Bei WinAC geht es, bei einer VIPA-Speed7 geht es nicht. Testweise würde ich mal eine beliebige Länge, die kleiner als die wirkliche Länge der Daten ist einstellen, dann mußt du etwas empfangen, auch wenn die Daten uim Buffer dann "rollieren". Sollte es so sein, dass nur eine Feste Länge ,möglich ist, dann hast du vielleicht ene Endekennung , die du dir mitschicken kannst? Du gibst dann eine Länge an, die größer als die zu sendenen Daten sind. Empfangene Daten werden dann immer hintereinander eingetragen, ist das Ende deines "Buffers" erreicht, wird vorn weitergemacht. Hat man eine immer gleiche Endekennung, dann kann man danach im empgangenen Datenstrim suchen, dich die Position für das nächste Mal merken usw. Ist nicht ganz ohne. Aber wie gesagt, die neueren SPS sollten das können, ich kenne leider keine Quelle, wo genau aufgelistet ist, an wann was geht.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hier mal, wie ich das damals gemacht habe, falls du es denn doch benötigst:

Code:
         fbTRCV(
           EN_R := connected AND NOT fbTRCV.NDR AND NOT Send.ACT AND NOT Init_error AND NOT Trigger_error,
           ID := ID,
           LEN := 0,
           DATA := Recv.Data);
           
         Recv.NDR := fbTRCV.NDR;
         Recv.Busy := fbTRCV.BUSY;
         Recv.Error := fbTRCV.ERROR; 
         Recv.Status := fbTRCV.STATUS; 
         Recv.LEN := fbTRCV.RCVD_LEN;    
 
    //check overflow buffer
    //Achtung, die empfangenen Daten sind unterschiedlich lang daher muß auf jeden Fall '$r' als Endekennung des Strings angehängt sein,
    //sonst kann nicht entschieden werden, ob der Buffer übergelaufen ist oder der String genau hineingepaßt hat
    
    IF ((RECV.LEN <> NextReceiveStartPos) AND (Recv.LEN <> 0) AND (Recv.LEN <> 100)) OR (Recv.NDR AND ((Recv.LEN <> 100) OR (Recv.Data[100] = '$r'))) THEN     
        Recv.Daten_receive := True; 
        LastReceiveStartPos := NextReceiveStartPos;
        NextReceiveStartPos := Recv.LEN;

        //Daten werden immer rollierend in den Buffer eingetragen und müssen nun 
        //dementsprechend dort herauskopiert werden.        

        //Daten im Buffer erst einmal löschen
        Code_Len := 0;
        FOR I := 1 TO 100 DO
            Code_Data[I] := INT_TO_CHAR(0);
            Error_Code[I] := INT_TO_CHAR(0);
        END_FOR;

        //Normalfall --> die Daten haben in den Buffer gepaßt
        IF NextReceiveStartPos >= LastReceiveStartPos THEN
            Rest_Len := 0;
            Receive_Len := NextReceiveStartPos - LastReceiveStartPos;
            IF Receive_Len > 100 THEN 
                Receive_Error := True; 
                Receive_Len := 0;
                NextReceiveStartPos := LastReceiveStartPos;
            END_IF;
                    
            //Code mit den empfangenen Daten füllen
            FOR I := 1 TO Receive_Len DO
                Code_Data[I] := Recv.Data[LastReceiveStartPos + I];
                Code_Len := Receive_Len;
            END_FOR; 
            
        ELSE;
        //Sonderfall --> die Daten haben nicht in den Buffer gepaßt
            Rest_Len := 101 - LastReceiveStartPos;
            Receive_Len := NextReceiveStartPos + 100 - LastReceiveStartPos;
            IF Receive_Len > 100 THEN 
                Receive_Error := True; 
                Receive_Len := 0;
                Rest_Len := 0;
                NextReceiveStartPos := LastReceiveStartPos;
            END_IF;
                    
            IF Rest_Len <= Receive_Len THEN
                //Code mit den empfangenen Daten bis Ende Buffer füllen
                FOR I := 1 TO Rest_Len DO
                  Code_Data[I] := Recv.Data[LastReceiveStartPos + I];
                END_FOR; 
                //Code mit den empfangenen Daten ab Anfang Buffer füllen  
                FOR I := Rest_Len TO Receive_Len DO
                   Code_Data[I] := Recv.Data[I - Rest_Len + 1];
                   Code_Len := Receive_Len;
                END_FOR;   
            END_IF;     
        END_IF;
    END_IF;
 
Sorry hab ich ganz vergessen die CPU ist eine 315_2 PN /DP ich hatte das schon mal mit einem anderen Baustein wo ich auch schon den FB64 benutze testhalber auf der selben CPU am Laufen dort bin ich aber hin und hab den Recive NDR dauerhaft auf True gesetzt jetzt hab ich die Bausteine nur umgeschrieben und auf die aktuelle Anwendung (Komunikation MIt einem Itac System ) die Strings nicht in die Instanzdatenbausteine zu kopieren
nur bekomm ich das mit dem Recive NDR nicht hin
 
Bei der Festen Länge kommt ja nicht immer das NDR, das kommt erst, wenn der Buffer voll ist, wenn ich das noch richtig im Kopf habe. Aber die Empfangene Länge bekommt einen Wert <> 0, daher diese unsägliche Konstruktion hier: ;)

Code:
IF ((RECV.LEN <> NextReceiveStartPos) AND (Recv.LEN <> 0) AND (Recv.LEN <> 100)) OR (Recv.NDR AND ((Recv.LEN <> 100) OR (Recv.Data[100] = '$r'))) THEN

Aber immer nur für einen Zyklus, versuch dir Received_LEN mal zu fangen. (Wenn <> 0 dann in eine Stat eintragen.)
 
Zurück
Oben