RS232 einlesen

Zuviel Werbung?
-> Hier kostenlos registrieren
@Thruser

Hier hab ich ein paar Änderungen gemacht (IF Abfragen + Arraygrenzen). sobald ich mit der Programmierung der Unterfunktion Nachrichten_Auswerten fertig werde, werde ich die hier posten.

Code:
GVL.SUC.Read(pRxBuffer := ADR(uC_READ),udiRxBufferSize:=SIZEOF(uC_READ));


For i:=0 TO (SIZEOF (uC_READ)-7) BY 1 DO
  IF uC_READ[i]= 10 AND uC_READ[i+1]= 13 AND uC_READ[i+2]= 10 AND uC_READ[i+3]=13 THEN
    i:=i+4;
    IF uC_Read[i+1]=10 AND uC_Read[i+2]=13 THEN
      Anzahl_der_Antworten:=uC_Read[i];
      Nachrichten_Auswerten(); // in diesem Baustein/Aktion werden die Nachrichtet ausgewertet

    ELSIF  uC_READ[i+4]= 10 AND uC_READ[i+5]= 13 AND uC_READ[i+6]= 10 AND uC_READ[i+7]=13 THEN

        Auswerten_Errorcode(); // in diesem Baustein/Aktion wird der Errorcodes ausgewertet
    END_IF
 
  END_IF
END_FOR




-----Ausweten_Errorcode()----


i:=i+4;


 A := ((uC_READ[i] AND 2#00000001) <> 0) OR A ;    // UKNOWN_Error
 B := ((uC_READ[i] AND 2#00000010) <> 0) OR B ;    // CAN_Error
 C := ((uC_READ[i] AND 2#00000100) <> 0) OR C ;    //Adressee_unkown
 D := ((uC_READ[i] AND 2#00001000) <> 0) OR D ;    //Parameter_unknow
 E := ((uC_READ[i] AND 2#00010000) <> 0) OR E ;     //Parameter_is_setable_only  
 F := ((uC_READ[i] AND 2#00100000) <> 0) OR F ;    //Parameter_is_getable_only 
 G := ((uC_READ[i] AND 2#01000000) <> 0) OR G ;      //Value_to_low
 H := ((uC_READ[i] AND 2#10000000) <> 0) OR H ;      //Value_to_high 
I := ((uC_READ[i+1] AND 2#00000001) <> 0) OR I ;    //Instruction_not_allowed
K := ((uC_READ[i+1] AND 2#00000010) <> 0) OR K ;    //Instruction_unkown
L := ((uC_READ[i+1] AND 2#00000100) <> 0) OR L ;   //Ask_priority_unkown
M := ((uC_READ[i+1] AND 2#00001000) <> 0) OR M ;    //Answer_priority_unkown

Gruß
 
Zuletzt bearbeitet:
Code:
A := uC_READ[i] AND 2#00000001 OR A ; // UKNOWN_Error
// u.s.w.
Verdammt, in diesem Thread ist mir der Klopper [SUP]1)[/SUP] ja auch schon unterlaufen! :oops:
Es muss heissen:
Code:
A := uC_READ[i] AND 2#00000001 <> 0 OR A ; // UKNOWN_Error
// u.s.w.
Zwei Bytes werden mit UND verknüpft und das Ergebnis ist natürlich wieder ein Byte (und kein BOOL).
Es muss der Vergleich mit 0 hinzu, dessen Ergebnis vom Typ BOOL ist, und das kann dann erst mit dem BOOL A verknüpft werden.
Sorry vielstmals!

Ich füge mal noch Klammern hinzu, die eigentlich nicht nötig sind (?), aber vielleicht helfen, zu verstehen:
A := ((uC_READ AND 2#00000001) <> 0) OR A ;

[SUP]1) [/SUP]siehe:
"WORD AND Bitmaske" ergibt wieder WORD (mit allen Bits = 0 die in der Bitmaske = 0 sind und höchstens den Bits = 1 die in der Bitmaske = 1 sind). Wenn nur das Bit (als BOOL) benötigt wird, dann noch das Ergebnis auf <> 0 vergleichen.
Bei S7-1500 kann man die Bits auch direkt per Slice-Zugriff ansprechen: BitstringVariable.%X..
Code:
Bit1 := (Wort AND 2#0000000000000010) <> 0 ;
Bit2 := (Wort AND 16#0004) <> 0 ;
Bit3 := Wort.%X3 ;  //Slice
Harald
 
Gibt der ST-Compiler bei den versuchten impliziten Konvertierungen zwischen BYTE und BOOL keine Fehler/Warnungen aus?
Kann man die Codesys-basierenden ST-Compiler ggf. zu weniger schlampigem Umgang mit Datentypen ("faule" implizite Konvertierungen) überreden (Pragma?)?

Harald
 
Gibt der ST-Compiler bei den versuchten impliziten Konvertierungen zwischen BYTE und BOOL keine Fehler/Warnungen aus?
Meinerseits war es keine "versuchte implizierte Konvertierung" - es war tatsächlich gründlich geschlampt (von mir)!
In dem Fall, um den es u.a. in diesem Thread geht, würde ich auch gar nicht erwarten, dass eine implizierte Konvertierung funktionieren kann. Wenn der Compiler nicht meckert, würde auch ich das als Schlamperei des Compilers bezeichnen!
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

ich weiß nicht, wie weit Du gekommen bist. Habe doch noch etwas Zeit gefunden.

Habe ein paar Test gemacht. Mit denen funktionierte es. Kann aber sein, daß ich nicht alle Fehlermöglichkeiten abgefangen habe.

Die Daten sollen eigentlich irgendwo im Byte Array liegen können, der Puffer kann also auch noch alten Datenmüll am Anfang haben.

Die Antworten der einzelnen Module werden in einer Struktur in einem Array ausgegeben. Das Array muß die gleiche Anzahl wie vorgegebene Module haben. Das wird überprüft, auch ob die Anzahl der Antworten der Modulzahl entspricht.

Code:
TYPE udtResponse :
STRUCT
    ModuleNumber : USINT;
    Instruction : USINT;
    Parameter : USINT;
    Value : UDINT;
    ErrorCode : UDINT;
END_STRUCT
END_TYPE

Und hier die Auswertung der Daten.
Code:
FUNCTION fcDecodeAnswer : UDINT
VAR_INPUT
    pData : POINTER TO BYTE;//Data
    udiDataSize : UINT;     //size of Data
    uiNoModules : USINT;    //Number of Modules
END_VAR
VAR_IN_OUT
    aResponse : ARRAY
[*] OF udtResponse;
END_VAR
VAR
    i : UINT;
    j : UINT;
    minLength : UINT;
    
    iState : INT := 0;
    
    uiNoAnswers : USINT;
    udiErrorCode : UDINT;
END_VAR

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

udiErrorCode := 16#80000000; // set general error decode

IF (UPPER_BOUND(aResponse,1)-LOWER_BOUND(aResponse,1)+1) <> uiNoModules THEN
    fcDecodeAnswer := udiErrorCode OR 16#40000000; //array for answers does not fit number of modules
    RETURN;
END_IF

IF udiDataSize < (11+19*uiNoModules) THEN
    fcDecodeAnswer := udiErrorCode OR 16#20000000;  //size of data to small
    RETURN;
END_IF

FOR i := TO_UINT(LOWER_BOUND(aResponse,1)) TO TO_UINT(UPPER_BOUND(aResponse,1)) DO
    aResponse[i].ErrorCode := 0;
    aResponse[i].Instruction := 0;
    aResponse[i].ModuleNumber := 0;
    aResponse[i].Parameter := 0;
    aResponse[i].Value := 0;
END_FOR

i := 0;
minLength := 12; //Trennzeichen+ErrorCode+Trennzeichen

WHILE i<(udiDataSize-minLength) DO
    CASE iState OF
        0 : //check for start of answer
            IF pData[i] = 10 AND pData[i+1] = 13 AND pData[i+2] = 10 AND pData[i+3] = 13 THEN
                iState := 10;
                i := i+4;
            ELSE
                i := i+1;
            END_IF
        10 : //check for number of answers or errorcode
            IF pData[i+1] = 10 AND pData[i+2] = 13 THEN
                uiNoAnswers := pData[i];
                IF uiNoAnswers <> uiNoModules THEN
                    udiErrorCode := udiErrorCode OR 16#10000000; //number of answers does not match number of modules 
                    iState := 100;
                END_IF
                iState := 20;
                i := i+3;
                minLength := uiNoAnswers*19+4;
                j := TO_UINT(LOWER_BOUND(aResponse,1));
            ELSIF pData[i+4] = 10 AND pData[i+5] = 13 AND pData[i+6] = 10 AND pData[i+7] = 13 THEN
                udiErrorCode := udiErrorCode OR 16#08000000 //errocode as answer
                                             OR (TO_UDINT(pData[i])   * 16#1000000 + 
                                                 TO_UDINT(pData[i+1]) * 16#10000 + 
                                                 TO_UDINT(pData[i+2]) * 16#100 + 
                                                 TO_UDINT(pData[i+3]));
                iState := 100;
            ELSE
                i := i-2; //no valid data check for next Trennzeichen
                minLength := 12;
                iState := 0;
            END_IF
        20 : //get module answer
            IF pData[i+1] = 9 AND pData[i+3] = 9 AND pData[i+5] = 9 AND pData[i+7] = 9 AND pData[i+12] = 9 AND pData[i+17] = 10 AND pData[i+18] = 13 THEN
                aResponse[j].ModuleNumber := pData[i+2];
                aResponse[j].Instruction := pData[i+4];
                aResponse[j].Parameter := pData[i+6];
                aResponse[j].Value := TO_UDINT(pData[i+8])  * 16#1000000 + 
                                      TO_UDINT(pData[i+9])  * 16#10000 + 
                                      TO_UDINT(pData[i+10]) * 16#100 + 
                                      TO_UDINT(pData[i+11]); 
                aResponse[j].ErrorCode := TO_UDINT(pData[i+13]) * 16#1000000 + 
                                          TO_UDINT(pData[i+14]) * 16#10000 + 
                                          TO_UDINT(pData[i+15]) * 16#100 + 
                                          TO_UDINT(pData[i+16]);
                IF aResponse[j].ErrorCode > 0 THEN
                    udiErrorCode := udiErrorCode OR 16#04000000; //at least on module has errorcode
                END_IF
                minLength :=  (TO_UINT(UPPER_BOUND(aResponse,1))-j)*19+4;
                j := j+1;
                i := i+19;
                IF j > TO_UINT(UPPER_BOUND(aResponse,1)) THEN
                    iState := 30;
                END_IF
            ELSE
                minLength := 12;//no valid data, check for next Trennzeichen
                iState := 0;
            END_IF
        30 : //check for end
            IF pData[i] = 10 AND pData[i+1] = 13 AND pData[i+2] = 10 AND pData[i+3] = 13 THEN
                iState := 40;
            ELSE
                minLength := 12;//no valid data, check for next Trennzeichen
                iState := 0;
                
            END_IF
        40 :
            IF (udiErrorCode AND 16#7FFFFFFF) = 0 THEN
                udiErrorCode := 0;
            END_IF
            iState := 100;
        100 : //finished
            i := udiDataSize;
    END_CASE
END_WHILE

fcDecodeAnswer := udiErrorCode;

Testdaten
Code:
    //aData01 : ARRAY[0..99] of byte := [16#0A, 16#0D, 16#0A, 16#0D, 16#11, 16#22, 16#33, 16#44, 16#0A, 16#0D, 16#0A, 16#0D];
    //aData01 : ARRAY[0..100] OF BYTE := [10(16#99), 16#0A, 16#0D, 16#0A, 16#0D, 16#03, 16#0A, 16#0D, 16#01, 16#09, 16#03, 16#09, 16#11, 16#09,16#22, 16#09,16#11, 16#22, 16#33, 16#44,16#09,16#F1, 16#F2, 16#F3, 16#F4,16#0A, 16#0D, 16#02, 16#09, 16#03, 16#09, 16#11, 16#09,16#22, 16#09,16#11, 16#22, 16#33, 16#44,16#09,16#F1, 16#F2, 16#F3, 16#F4,16#0A, 16#0D, 16#03, 16#09, 16#03, 16#09, 16#11, 16#09,16#22, 16#09,16#11, 16#22, 16#33, 16#44, 16#09, 16#F1, 16#F2, 16#F3, 16#F4, 16#0A, 16#0D, 16#0A, 16#0D, 16#0A, 16#0D];
    aData01 : ARRAY[0..100] OF BYTE := [10(16#99), 16#0A, 16#0D, 16#0A, 16#0D, 16#03, 16#0A, 16#0D, 16#01, 16#09, 16#03, 16#09, 16#11, 16#09,16#22, 16#09,16#11, 16#22, 16#33, 16#44,16#09,16#00, 16#00, 16#00, 16#00,16#0A, 16#0D, 16#02, 16#09, 16#03, 16#09, 16#11, 16#09,16#22, 16#09,16#11, 16#22, 16#33, 16#44,16#09,16#00, 16#00, 16#00, 16#00,16#0A, 16#0D, 16#03, 16#09, 16#03, 16#09, 16#11, 16#09,16#22, 16#09,16#11, 16#22, 16#33, 16#44, 16#09, 16#00, 16#00, 16#00, 16#00, 16#0A, 16#0D, 16#0A, 16#0D, 16#0A, 16#0D];

Trotzdem wirst Du Dir aber auch noch etwas wegen des Read Befehls überlegen müssen. Denn Du wirst die gesamte Antwort nicht in einem Zyklus erhalten und auch nicht dirket nachdem Du den Write Befehl ausgeführt hast.

Das mag vielleicht so am PC aussehen, aber die SPS benötigt etwas Zeit bis die Nachricht wirklich über die Schnittstelle versendet ist. Dann muß die Gegenseite diese entgegennehmen, verarbeiten und dann Antworten. Daher kann es sein das mehrere SPS Zyklen vergehen bis Du durch die Read Funktion Daten erhälst.

Gruß
 
@Thruser
Vielen Vielen dank.

kannst du mir bitte sagen ob dieser aufruf der Funktion so stimmt (aResponse Wert zuweisung)??

Code:
VAR
aData01 : ARRAY[0..100] OF BYTE := [10(16#99), 16#0A, 16#0D, 16#0A, 16#0D, 16#03, 16#0A, 16#0D, 16#01, 16#09, 16#03, 16#09, 16#11, 16#09,16#22, 16#09,16#11, 16#22, 16#33, 16#44,16#09,16#00, 16#00, 16#00, 16#00,16#0A, 16#0D, 16#02, 16#09, 16#03, 16#09, 16#11, 16#09,16#22, 16#09,16#11, 16#22, 16#33, 16#44,16#09,16#00, 16#00, 16#00, 16#00,16#0A, 16#0D, 16#03, 16#09, 16#03, 16#09, 16#11, 16#09,16#22, 16#09,16#11, 16#22, 16#33, 16#44, 16#09, 16#00, 16#00, 16#00, 16#00, 16#0A, 16#0D, 16#0A, 16#0D, 16#0A, 16#0D];


OUT: UDINT;
hi: ARRAY[1..3] OF udtResponse;
END_VAR
******************************
OUT:=fcDecodeAnswer(pData:= ADR(aData01), udiDataSize:= SIZEOF(aData01), uiNoModules:=3, aResponse:= hi);

Beste Grüße und noch einmal vielen dank
 
Zurück
Oben