IO-Link Kommunikation per S7comm

Zuviel Werbung?
-> Hier kostenlos registrieren
Aber woher weiß der nackte RDREC, dass du Index 18, Subindex 0 lesen willst?
Was stehen bei der RDREC-Antwort noch für Bytes vor dem eigentlichen String, bestehen dort Ähnlichkeiten zu denen die auf dem Netzwerk zu sehen sind?
 
Aber woher weiß der nackte RDREC, dass du Index 18, Subindex 0 lesen willst?
Was stehen bei der RDREC-Antwort noch für Bytes vor dem eigentlichen String, bestehen dort Ähnlichkeiten zu denen die auf dem Netzwerk zu sehen sind?

RDREC scheint immer einen Header + die durch den IO-Link angewählten Nutzdaten zu lesen.

Vorgehen: IOL Baustein ausgeführt und anschließend den RDREC

ID300-CAP227-Port1-Index2-Sub0.jpgID300-CAP227-Port1-Index1-Sub0.jpgID300-CAP227-Port1-Index0-Sub0.jpg
 
Du hast bei deiner AWL-Quelle vermutlich den IO_LINK_MASTER gepostet, von dem liefert Siemens auch die SCL-Quelle mit.

Wenn man aber in den IO_LINK_DEVICE reinschaut, dann sieht man zumindest in den STAT-Variablen in der Struct "read.header" den Aufbau des Datenteils das auch übers Netzwerk geht. Glücklicherweise mit Kommentar :) Leider fehlt hier die SCL-Quelle, müsste man sich anfertigen wenn das weiterhilft.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du hast bei deiner AWL-Quelle vermutlich den IO_LINK_MASTER gepostet, von dem liefert Siemens auch die SCL-Quelle mit.
IO_LINK_MASTER_4
Ist als SCL gleich viel übersichtlicher :)

Sollte eigentlich IO_LINK_DEVICE sein.

rwIOL (Screenshot) entspricht IO_LINK_DEVICE
 
Zuletzt bearbeitet:
Bei TIA sind die SCL Quellen dabei.

IO_LINK_DEVICE_FB_300
Code:
(*---------------------------------------------------------------------------------------------------------------------
SIEMENS AG
©Copyright 2015. All Rights Reserved.
-----------------------------------------------------------------------------------------------------------------------
Limitation of liability
This software was developed with largest care. However, the author can not guarantee, that the software runs under
each version of STEP7 on each PLC flawlessly.
There is no warranty for the software, to the extent permitted by applicable law. The copyright holder provides the
software "as is" without warranty of any kind, either expressed or implied, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose. The entire risk as to the quality and performance
of the software is with you. Should the software prove defective, you assume the cost of all necessary servicing,
repair or correction. In no event unless required by applicable law will the copyright holder be liable to you for
damages, including any general, special, incidental or consequential damages arising out of the use or inability to
use the software (including but not limited to loss of data or data being rendered inaccurate or losses sustained by
you or third parties or a failure of the software to operate with any other programs), even if such holder or other
party has been advised of the possibility of such damages.
Permission to use or copy this software for any purpose is hereby granted without fee, provided the above notices are
retained on all copies. Permission to modify the code and to distribute modified code is granted, provided the above
notices are retained, and a notice that the code was modified is included with the above copyright notice.
-----------------------------------------------------------------------------------------------------------------------
Functionality provided by this source (short description):
Function block IO_LINK_DEVICE - used to read and write of acyclic data records on devices with IO-Link.
Note:
To read data records, the IO-Link master modules needs to know which data record is required. Therefore it is necessary
to send at first a request via write data record (only header of 8 byte). As response the IO-Link master module
will send the required data record.


Status:     Released (tested)
File name:  IO_LINK_DEVICE
System :    SIMATIC S7-300/400
Version :   3.0
-----------------------------------------------------------------------------------------------------------------------
Script to be stored on level ... in project (mark appropriate levels with [x] below)
[ ] External
[ ] All levels possible
[x] Project level
[ ] Controller level
[ ] Device level
[ ] Subobject level
-----------------------------------------------------------------------------------------------------------------------
Restrictions, known limitations:
The limitation of 240 byte is based on PROFIBUS DP protocol. With PROFINET IO there wouldn't no limit but because of 
compatibility reason it wasn't changed.
  - header =   8 byte
  - data   = 232 byte
-----------------------------------------------------------------------------------------------------------------------
Requirements, prerequisites, External resources used: nothing
-----------------------------------------------------------------------------------------------------------------------
Change log table (latest change is at the bottom OF the list):
Version Date Changes applied
V2.0.0 <2013-09-30> First created with TIA Portal V12 SP1
V2.1.0 <2014-03-14> Upgrade system function 'WRREC' from V1.0 to V1.1 and released for TIA Portal V13
V3.0.0 <2015-02-28> Upgrade and released for TIA Portal V13 SP1 (without backup/restore master parameter)
V3.0.1 <2015-07-07> Change of #IOL_INDEX and #Port lower boundry to 0
---------------------------------------------------------------------------------------------------------------------*)


(*---------------------------------------------------------------------------------------------------------------------
Description of programmed IO-Link error codes
8000 = time out
8001 = wrong port
8002 = wrong index
8003 = wrong subindex
8005 = wrong length for write data record
8006 = wrong length for read data record
8052 = error during reading data record
8053 = error during writing data record
All other codes are coming from a higher level!
---------------------------------------------------------------------------------------------------------------------*)


(*---------------------------------------------------------------------------------------------------------------------
            NEW REQUEST
---------------------------------------------------------------------------------------------------------------------*)
// detection rising edge of "REQ"
#R_TRIG_REQ := #REQ = TRUE AND #R_TRIG_REQ_old = FALSE;
#R_TRIG_REQ_old := #REQ = TRUE;


// start new request if not busy
IF #R_TRIG_REQ = TRUE AND #sequencecontrol = 0 THEN
    // Freeze record ID and CAP
    #WRREC_Function.ID := #ID;
    #WRREC_Function.INDEX := #CAP;
    #RDREC_Function.ID := #ID;
    #RDREC_Function.INDEX := #CAP;
    
    // Initialize outputs
    #DONE_VALID := FALSE;
    #BUSY := TRUE;
    #ERROR := FALSE;
    #STATUS := DW#16#00000000;
    #IOL_STATUS := DW#16#00000000;
    #RD_LEN := INT#0;
    
    // Initialize data area
    #read.header."CALL"."Port" := B#16#0;
    #read.header.IOL.Index_LowByte := B#16#0;
    #read.header.IOL.Index_HighByte := B#16#0;
    #read.header.IOL.Subindex := B#16#0;
    #i := INT#0; // initialize loop counter      
    FOR #i := 0 TO 231 DO
        #write.data[#i] := B#16#0;
        #read.data[#i] := B#16#0;
    END_FOR;
    
(*---------------------------------------------------------------------------------------------------------------------
    Setup IO-LINK Call needs a specific header
---------------------------------------------------------------------------------------------------------------------*)
// setup CALL header
#write.header."CALL".Extended_Function_Num := 16#08;  // extended function number (fix coded 08h)
#write.header."CALL"."Port" := INT_TO_BYTE(#PORT);  // 1..63 = PORT number, 64..255=reserved
#write.header."CALL".FI_Index := 65098;  // IOL-Header is following (fix coded 65098)


// setup IOL header 
// CONTROL = please see below at BODY
// INDEX
#write.header.IOL.Index_LowByte := INT_TO_BYTE(#IOL_INDEX);
#tmpWORD := INT_TO_WORD(#IOL_INDEX);
#tmpWORD := SHR(IN := #tmpWORD, N := 8);
#write.header.IOL.Index_HighByte := WORD_TO_BYTE(#tmpWORD);
// SUBINDEX
#write.header.IOL.Subindex := INT_TO_BYTE(#IOL_SUBINDEX);


// BODY (data max. 232 Byte, Array 0..231 of Byte) 
IF #RD_WR = TRUE THEN
    // IO-Link write data record requested, copy data from "RECORD_IOL_DATA"
    #write.header.IOL.Control := B#16#02; // CONTROL B#16#02 = write data record
    #wrrec.length := #LEN + INT#8;  // data length header + data = IO-Link write data record
    #typeofrequest := 2; // write data record
    // copy IOL_RECORD_DATA in working area
    #i := INT#0;    // initialize loop counter 
    FOR #i := 0 TO #LEN - 1 DO
        #write.data[#i] := #RECORD_IOL_DATA[#i];
    END_FOR;
ELSE
    // IO-Link read data record requested
    #write.header.IOL.Control := 16#03;  // CONTROL 16#03 = read data record
    #wrrec.length := INT#8; // data length only header = IO-Link read data record
    #typeofrequest := 1; // read data record        
END_IF;
#sequencecontrol := 1;  // Start sequence
ELSE
    ;
END_IF;


(*---------------------------------------------------------------------------------------------------------------------
            SEQUENCE CONTROL
---------------------------------------------------------------------------------------------------------------------*)
CASE #sequencecontrol OF
    1:  // Check input parameter        
        IF #PORT < INT#0 OR #PORT > INT#63 THEN // PORT (Wrong port address = 0x8001)
            #ERROR := TRUE;
            #IOL_STATUS := DW#16#80010000;
            #sequencecontrol := 99; // aborting function with error
        ELSIF #IOL_INDEX < INT#0 OR #IOL_INDEX > INT#32767 THEN    // INDEX (Wrong index = 0x8002)
            #ERROR := TRUE;
            #IOL_STATUS := DW#16#80020000;
            #sequencecontrol := 99; // aborting function with error
        ELSIF #IOL_SUBINDEX < INT#0 OR #IOL_SUBINDEX > INT#255 THEN    // SUBINDEX (Wrong subindex = 0x8003)
            #ERROR := TRUE;
            #IOL_STATUS := DW#16#80030000;
            #sequencecontrol := 99; // aborting function with error
        ELSIF #typeofrequest = 2 AND (#LEN < 1 OR #LEN > 232) THEN  // LEN (wrong length for write data record = 0x8004)
            #ERROR := TRUE;
            #IOL_STATUS := DW#16#80050000;
            #sequencecontrol := 99; // aborting function with error
        ELSIF #typeofrequest = 1 AND (#LEN < 0 OR #LEN > 232) THEN  // LEN (wrong length for read data record = 0x8005)
            #ERROR := TRUE;
            #IOL_STATUS := DW#16#80060000;
            #sequencecontrol := 99; // aborting function with error
        ELSE    // all input parameter are right
            #sequencecontrol := 2;
        END_IF;
        
    2:  (*-------------------------------------------------------------------------------------------------------------
        WRREC = Write Data Record
        Note:
        To read data records, the IO-Link master modules needs to know which PORT is required. Therefore it is necessary
        to send at first a request via write data record (header, 8 byte). As response the IO-Link master module will 
        send the required data record.
        -------------------------------------------------------------------------------------------------------------*)
        #WRREC_Function(REQ := TRUE,
                        LEN := #wrrec.length,
                        DONE => #wrrec.done,
                        BUSY => #wrrec.busy,
                        ERROR => #wrrec.error,
                        STATUS => #wrrec.status,
                        RECORD := #write);
        // output status during write data record
        IF #wrrec.busy THEN
            #STATUS := #wrrec.status;
            #IOL_STATUS := DW#16#00020000;  // 0002 = writing in progress 
        ELSIF #wrrec.error THEN
            #tmpDWORD := #wrrec.status AND DW#16#00FFFF00;  // filter status
            IF #tmpDWORD = DW#16#0080C200 THEN    // if resource #BUSY (#STATUS=80C2), then ... 
                #sequencecontrol := 3;  // ... repeat write data record
            ELSE
                #ERROR := TRUE;
                #STATUS := #wrrec.status;   // ... otherwise output error status of "WRREC"
                #IOL_STATUS := DW#16#80530000;  // ... with note '8053' = error status of "WRREC"
                #sequencecontrol := 99; // aborting function with error
            END_IF;
        ELSIF #wrrec.done = TRUE THEN   // wait for write data record finish without error
            #TP_poll(IN := TRUE,
                     PT := T#100ms);    // poll for response
            #sequencecontrol := 4;
        ELSE
            ;
        END_IF;
        
    3:  // repeat write data record because resource was busy
        #WRREC_Function(REQ := FALSE);
        #sequencecontrol := 2;
        
    4:  // wait and poll for response = Read Data Record (RDREC)
        #WRREC_Function(REQ := FALSE);
        #TP_poll(IN := TRUE,
                 PT := T#100ms);
        
        // if poll rate executed then start read data record (on falling edge)
        #F_TRIG_poll := #TP_poll.Q = FALSE AND #F_TRIG_poll_old = TRUE;
        #F_TRIG_poll_old := #TP_poll.Q = TRUE;
        
        // RDREC = Read Data Record
        #RDREC_Function(REQ := #F_TRIG_poll,
                        MLEN := INT#232, // max. length = 232 = read all data which are available
                        VALID => #rdrec.valid,
                        BUSY => #rdrec.busy,
                        ERROR => #rdrec.error,
                        STATUS => #rdrec.status,
                        LEN => #rdrec.length,
                        RECORD := #read);
        // output status during read data record
        IF #rdrec.busy THEN
            #STATUS := #rdrec.status;
            #IOL_STATUS := DW#16#00030000; // 16#0003 = reading in progress
        ELSIF #rdrec.error = TRUE THEN
            #tmpDWORD := #rdrec.status AND DW#16#00FFFF00;  // filter status
            IF #tmpDWORD = DW#16#0080C200 THEN  // if resource busy (status=80C2), then ... 
                #sequencecontrol := 5;  // ... repeat read data record / continue polling
            ELSE
                #ERROR := TRUE;
                #STATUS := #rdrec.status;   // ... otherwise output error code of "RDREC"
                #IOL_STATUS := DW#16#80520000;  // ... with note '8052' = error status of "RDREC"
                #sequencecontrol := 99; // aborting function with error
            END_IF;
        ELSIF #rdrec.valid THEN
            IF  // check the response wether it matches the request (compare PORT, INDEX and SUBINDEX)
                (#write.header."CALL"."Port" <> #read.header."CALL"."Port") OR
                (#write.header.IOL.Index_HighByte <> #read.header.IOL.Index_HighByte) OR
                (#write.header.IOL.Index_LowByte <> #read.header.IOL.Index_LowByte) OR
                (#write.header.IOL.Subindex <> #read.header.IOL.Subindex)
            THEN    // read data record don't match the request
                #ERROR := TRUE;
                #STATUS := #rdrec.status;
                #IOL_STATUS := DW#16#70000000;  // output status '7000', no consistent data
                #sequencecontrol := 99; // aborting function with error
            ELSIF #read.header.IOL.Control = B#16#80 THEN   // check the response for IO-Link errors
                // State 0x80 = IOL_CALL_RES PDU shows IO-Link error detect
                #ERROR := TRUE;
                #STATUS := DW#16#00000000;
                #AT_IOL_STATUS[3] := #read.data[3];   // IO-Link master error code
                #AT_IOL_STATUS[2] := #read.data[2];   // IO-Link master error code
                #AT_IOL_STATUS[1] := #read.data[1];  // IO-Link device error code
                #AT_IOL_STATUS[0] := #read.data[0];  // IO-Link device additional error code
                #IOL_STATUS := #tmpDWORD;
                #sequencecontrol := 99; // aborting function with error
            ELSE    // read data are valid = output
                #DONE_VALID := TRUE;
                #BUSY := FALSE;
                #ERROR := FALSE;
                #STATUS := DW#16#00000000;
                #IOL_STATUS := DW#16#00000000;  // request finished
                
                IF #typeofrequest = 1 THEN
                    #RD_LEN := #rdrec.length - INT#8;  // device parameter cover header and data,
                    // only data will be output
                    #i := INT#0; // initialize loop counter
                    FOR #i := 0 TO #rdrec.length - INT#8 - INT#1 DO
                        #RECORD_IOL_DATA[#i] := #read.data[#i];
                    END_FOR;
                ELSE
                    ;
                END_IF;
                #sequencecontrol := 98;
            END_IF;
        ELSE
            ;
        END_IF;
        
    5:  // poll again for response because resource was busy
        #TP_poll(IN := FALSE,
                 PT := T#100ms);
        #RDREC_Function(REQ := FALSE,
                        RECORD := #read);
        #sequencecontrol := 4;  // ... repeat read data record / continue polling   
        
    98: // request done successfully
        #TP_poll(IN := FALSE,
                 PT := T#100ms);
        #RDREC_Function(REQ := FALSE,
                        RECORD := #read);
        IF #REQ = FALSE THEN
            #DONE_VALID := FALSE;
            #BUSY := FALSE;
            #ERROR := FALSE;
            #RD_LEN := INT#0;
            #STATUS := DW#16#00000000;
            #IOL_STATUS := DW#16#00010000; // ready for new request
            #sequencecontrol := 0;
            #typeofrequest := 0;
        ELSE
            ;
        END_IF;
        
    99: // Function aborted with error
        #TP_poll(IN := FALSE,
                 PT := T#100ms);
        #WRREC_Function(REQ := FALSE);
        #RDREC_Function(REQ := FALSE,
                        RECORD := #read);
        #DONE_VALID := FALSE;
        #BUSY := FALSE;
        #RD_LEN := INT#0;
        #sequencecontrol := 0;
        #typeofrequest := 0;
        
    ELSE  // no relevant case, ready for new request
        #WRREC_Function(REQ := FALSE);
        #RDREC_Function(REQ := FALSE,
                        RECORD := #read);
        #TP_poll(IN := FALSE,
                 PT := T#100ms);
        #TON_monitoring(IN := FALSE,
                        PT := T#20s);
        #sequencecontrol := 0;
        #typeofrequest := 0;
END_CASE;


(*---------------------------------------------------------------------------------------------------------------------
            MONITORING
---------------------------------------------------------------------------------------------------------------------*)
#TON_monitoring(IN := #sequencecontrol > 0 AND #sequencecontrol < 98,
                PT := T#20s);
IF #TON_monitoring.Q THEN
    #ERROR := TRUE;
    #IOL_STATUS := DW#16#80000000; // request time out       
    #sequencecontrol := 99; // aborting function with error
END_IF;

IO_LINK_DEVICE_FB_1200 / IO_LINK_DEVICE_FB_1500
Code:
(*---------------------------------------------------------------------------------------------------------------------
SIEMENS AG
©Copyright 2015. All Rights Reserved.
-----------------------------------------------------------------------------------------------------------------------
Limitation of liability
This software was developed with largest care. However, the author can not guarantee, that the software runs under
each version of STEP7 on each PLC flawlessly.
There is no warranty for the software, to the extent permitted by applicable law. The copyright holder provides the
software "as is" without warranty of any kind, either expressed or implied, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose. The entire risk as to the quality and performance
of the software is with you. Should the software prove defective, you assume the cost of all necessary servicing,
repair or correction. In no event unless required by applicable law will the copyright holder be liable to you for
damages, including any general, special, incidental or consequential damages arising out of the use or inability to
use the software (including but not limited to loss of data or data being rendered inaccurate or losses sustained by
you or third parties or a failure of the software to operate with any other programs), even if such holder or other
party has been advised of the possibility of such damages.
Permission to use or copy this software for any purpose is hereby granted without fee, provided the above notices are
retained on all copies. Permission to modify the code and to distribute modified code is granted, provided the above
notices are retained, and a notice that the code was modified is included with the above copyright notice.
-----------------------------------------------------------------------------------------------------------------------
Functionality provided by this source (short description):
Function block IO_LINK_DEVICE - used to read and write of acyclic data records on devices with IO-Link.
Note:
To read data records, the IO-Link master modules needs to know which data record is required. Therefore it is necessary
to send at first a request via write data record (only header of 8 byte). As response the IO-Link master module
will send the required data record.


Status:     Released (tested)
File name:  IO_LINK_DEVICE
System :    SIMATIC S7-1200/1500
Version :   3.0
-----------------------------------------------------------------------------------------------------------------------
Script to be stored on level ... in project (mark appropriate levels with [x] below)
[ ] External
[ ] All levels possible
[x] Project level
[ ] Controller level
[ ] Device level
[ ] Subobject level
-----------------------------------------------------------------------------------------------------------------------
Restrictions, known limitations:
The limitation of 240 byte is based on PROFIBUS DP protocol. With PROFINET IO there wouldn't no limit but because of 
compatibility reason it wasn't changed.
  - header =   8 byte
  - data   = 232 byte
-----------------------------------------------------------------------------------------------------------------------
Requirements, prerequisites, External resources used: nothing
-----------------------------------------------------------------------------------------------------------------------
Change log table (latest change is at the bottom OF the list):
Version Date Changes applied
V2.0.0 <2013-09-30> First created with TIA Portal V12 SP1
V2.1.0 <2014-03-14> Upgrade system function 'WRREC' from V1.0 to V1.1 and released for TIA Portal V13
V3.0.0 <2015-02-28> Upgrade and released for TIA Portal V13 SP1 (without backup/restore master parameter)
V3.0.2 <2015-07-07> Change of #IOL_INDEX and #Port lower boundry to 0
---------------------------------------------------------------------------------------------------------------------*)


(*---------------------------------------------------------------------------------------------------------------------
Description of programmed IO-Link error codes
8000 = time out
8001 = wrong port
8002 = wrong index
8003 = wrong subindex
8005 = wrong length for write data record
8006 = wrong length for read data record
8052 = error during reading data record
8053 = error during writing data record
All other codes are coming from a higher level!
---------------------------------------------------------------------------------------------------------------------*)


(*---------------------------------------------------------------------------------------------------------------------
            NEW REQUEST
---------------------------------------------------------------------------------------------------------------------*)
// detection rising edge of "REQ"
#R_TRIG_REQ := #REQ = TRUE AND #R_TRIG_REQ_old = FALSE;
#R_TRIG_REQ_old := #REQ = TRUE;


// start new request if not busy
IF #R_TRIG_REQ = TRUE AND #sequencecontrol = 0 THEN
    // Freeze record ID and CAP
    #WRREC_Function.ID := #ID;
    #WRREC_Function.INDEX := #CAP;
    #RDREC_Function.ID := #ID;
    #RDREC_Function.INDEX := #CAP;
    
    // Initialize outputs
    #DONE_VALID := FALSE;
    #BUSY := TRUE;
    #ERROR := FALSE;
    #STATUS := DW#16#00000000;
    #IOL_STATUS := DW#16#00000000;
    #RD_LEN := INT#0;
    
    // Initialize data area
    #read.header."CALL"."Port" := B#16#0;
    #read.header.IOL.Index_LowByte := B#16#0;
    #read.header.IOL.Index_HighByte := B#16#0;
    #read.header.IOL.Subindex := B#16#0;
    #i := INT#0; // initialize loop counter      
    FOR #i := 0 TO 231 DO
        #write.data[#i] := B#16#0;
        #read.data[#i] := B#16#0;
    END_FOR;
    
(*---------------------------------------------------------------------------------------------------------------------
    Setup IO-LINK Call needs a specific header
---------------------------------------------------------------------------------------------------------------------*)
// setup CALL header
#write.header."CALL".Extended_Function_Num := 16#08;  // extended function number (fix coded 08h)
#write.header."CALL"."Port" := INT_TO_BYTE(#PORT);  // 1..63 = PORT number, 64..255=reserved
#write.header."CALL".FI_Index := 65098;  // IOL-Header is following (fix coded 65098)


// setup IOL header 
// CONTROL = please see below at BODY
// INDEX
#write.header.IOL.Index_LowByte := INT_TO_BYTE(#IOL_INDEX);
#tmpWORD := INT_TO_WORD(#IOL_INDEX);
#tmpWORD := SHR(IN := #tmpWORD, N := 8);
#write.header.IOL.Index_HighByte := WORD_TO_BYTE(#tmpWORD);
// SUBINDEX
#write.header.IOL.Subindex := INT_TO_BYTE(#IOL_SUBINDEX);


// BODY (data max. 232 Byte, Array 0..231 of Byte) 
IF #RD_WR = TRUE THEN
    // IO-Link write data record requested, copy data from "RECORD_IOL_DATA"
    #write.header.IOL.Control := B#16#02; // CONTROL B#16#02 = write data record
    #wrrec.length := INT_TO_UINT(#LEN) + UINT#8;  // data length header + data = IO-Link write data record
    #typeofrequest := 2; // write data record
    // copy IOL_RECORD_DATA in working area
    #i := INT#0;    // initialize loop counter 
    FOR #i := 0 TO #LEN - 1 DO
        #write.data[#i] := #RECORD_IOL_DATA[#i];
    END_FOR;
ELSE
    // IO-Link read data record requested
    #write.header.IOL.Control := 16#03;  // CONTROL 16#03 = read data record
    #wrrec.length := UINT#8; // data length only header = IO-Link read data record
    #typeofrequest := 1; // read data record        
END_IF;
#sequencecontrol := 1;  // Start sequence
ELSE
    ;
END_IF;


(*---------------------------------------------------------------------------------------------------------------------
            SEQUENCE CONTROL
---------------------------------------------------------------------------------------------------------------------*)
CASE #sequencecontrol OF
    1:  // Check input parameter        
        IF #PORT < INT#0 OR #PORT > INT#63 THEN // PORT (Wrong port address = 0x8001)
            #ERROR := TRUE;
            #IOL_STATUS := DW#16#80010000;
            #sequencecontrol := 99; // aborting function with error
        ELSIF #IOL_INDEX < INT#0 OR #IOL_INDEX > INT#32767 THEN    // INDEX (Wrong index = 0x8002)
            #ERROR := TRUE;
            #IOL_STATUS := DW#16#80020000;
            #sequencecontrol := 99; // aborting function with error
        ELSIF #IOL_SUBINDEX < INT#0 OR #IOL_SUBINDEX > INT#255 THEN    // SUBINDEX (Wrong subindex = 0x8003)
            #ERROR := TRUE;
            #IOL_STATUS := DW#16#80030000;
            #sequencecontrol := 99; // aborting function with error
        ELSIF #typeofrequest = 2 AND (#LEN < 1 OR #LEN > 232) THEN  // LEN (wrong length for write data record = 0x8004)
            #ERROR := TRUE;
            #IOL_STATUS := DW#16#80050000;
            #sequencecontrol := 99; // aborting function with error
        ELSIF #typeofrequest = 1 AND (#LEN < 0 OR #LEN > 232) THEN  // LEN (wrong length for read data record = 0x8005)
            #ERROR := TRUE;
            #IOL_STATUS := DW#16#80060000;
            #sequencecontrol := 99; // aborting function with error
        ELSE    // all input parameter are right
            #sequencecontrol := 2;
        END_IF;
        
    2:  (*-------------------------------------------------------------------------------------------------------------
        WRREC = Write Data Record
        Note:
        To read data records, the IO-Link master modules needs to know which PORT is required. Therefore it is necessary
        to send at first a request via write data record (header, 8 byte). As response the IO-Link master module will 
        send the required data record.
        -------------------------------------------------------------------------------------------------------------*)
        #WRREC_Function(REQ := TRUE,
                        LEN := #wrrec.length,
                        DONE => #wrrec.done,
                        BUSY => #wrrec.busy,
                        ERROR => #wrrec.error,
                        STATUS => #wrrec.status,
                        RECORD := #write);
        // output status during write data record
        IF #wrrec.busy THEN
            #STATUS := #wrrec.status;
            #IOL_STATUS := DW#16#00020000;  // 0002 = writing in progress 
        ELSIF #wrrec.error THEN
            #tmpDWORD := #wrrec.status AND DW#16#00FFFF00;  // filter status
            IF #tmpDWORD = DW#16#0080C200 THEN    // if resource #BUSY (#STATUS=80C2), then ... 
                #sequencecontrol := 3;  // ... repeat write data record
            ELSE
                #ERROR := TRUE;
                #STATUS := #wrrec.status;   // ... otherwise output error status of "WRREC"
                #IOL_STATUS := DW#16#80530000;  // ... with note '8053' = error status of "WRREC"
                #sequencecontrol := 99; // aborting function with error
            END_IF;
        ELSIF #wrrec.done = TRUE THEN   // wait for write data record finish without error
            #TP_poll(IN := TRUE,
                     PT := T#100ms);    // poll for response
            #sequencecontrol := 4;
        ELSE
            ;
        END_IF;
        
    3:  // repeat write data record because resource was busy
        #WRREC_Function(REQ := FALSE);
        #sequencecontrol := 2;
        
    4:  // wait and poll for response = Read Data Record (RDREC)
        #WRREC_Function(REQ := FALSE);
        #TP_poll(IN := TRUE,
                 PT := T#100ms);
        
        // if poll rate executed then start read data record (on falling edge)
        #F_TRIG_poll := #TP_poll.Q = FALSE AND #F_TRIG_poll_old = TRUE;
        #F_TRIG_poll_old := #TP_poll.Q = TRUE;
        
        // RDREC = Read Data Record
        #RDREC_Function(REQ := #F_TRIG_poll,
                        MLEN := UINT#0, // length = 0 = read all data which are available
                        VALID => #rdrec.valid,
                        BUSY => #rdrec.busy,
                        ERROR => #rdrec.error,
                        STATUS => #rdrec.status,
                        LEN => #rdrec.length,
                        RECORD := #read);
        // output status during read data record
        IF #rdrec.busy THEN
            #STATUS := #rdrec.status;
            #IOL_STATUS := DW#16#00030000; // 16#0003 = reading in progress
        ELSIF #rdrec.error = TRUE THEN
            #tmpDWORD := #rdrec.status AND DW#16#00FFFF00;  // filter status
            IF #tmpDWORD = DW#16#0080C200 THEN  // if resource busy (status=80C2), then ... 
                #sequencecontrol := 5;  // ... repeat read data record / continue polling
            ELSE
                #ERROR := TRUE;
                #STATUS := #rdrec.status;   // ... otherwise output error code of "RDREC"
                #IOL_STATUS := DW#16#80520000;  // ... with note '8052' = error status of "RDREC"
                #sequencecontrol := 99; // aborting function with error
            END_IF;
        ELSIF #rdrec.valid THEN
            IF  // check the response wether it matches the request (compare PORT, INDEX and SUBINDEX)
                (#write.header."CALL"."Port" <> #read.header."CALL"."Port") OR
                (#write.header.IOL.Index_HighByte <> #read.header.IOL.Index_HighByte) OR
                (#write.header.IOL.Index_LowByte <> #read.header.IOL.Index_LowByte) OR
                (#write.header.IOL.Subindex <> #read.header.IOL.Subindex)
            THEN    // read data record don't match the request
                #ERROR := TRUE;
                #STATUS := #rdrec.status;
                #IOL_STATUS := DW#16#70000000;  // output status '7000', no consistent data
                #sequencecontrol := 99; // aborting function with error
            ELSIF #read.header.IOL.Control = B#16#80 THEN   // check the response for IO-Link errors
                // State 0x80 = IOL_CALL_RES PDU shows IO-Link error detect
                #ERROR := TRUE;
                #STATUS := DW#16#00000000;
                #IOL_STATUS.%B3 := #read.data[0];   // IO-Link master error code
                #IOL_STATUS.%B2 := #read.data[1];   // IO-Link master error code
                #IOL_STATUS.%B1 := #read.data[2];  // IO-Link device error code
                #IOL_STATUS.%B0 := #read.data[3];  // IO-Link device additional error code
                
                #sequencecontrol := 99; // aborting function with error
            ELSE    // read data are valid = output
                #DONE_VALID := TRUE;
                #BUSY := FALSE;
                #ERROR := FALSE;
                #STATUS := DW#16#00000000;
                #IOL_STATUS := DW#16#00000000;  // request finished
                
                IF #typeofrequest = 1 THEN
                    #RD_LEN := UINT_TO_INT(#rdrec.length - UINT#8);  // device parameter cover header and data,
                    // only data will be output
                    #i := INT#0; // initialize loop counter
                    FOR #i := 0 TO UINT_TO_INT(#rdrec.length - UINT#8 - UINT#1) DO
                        #RECORD_IOL_DATA[#i] := #read.data[#i];
                    END_FOR;
                ELSE
                    ;
                END_IF;
                #sequencecontrol := 98;
            END_IF;
        ELSE
            ;
        END_IF;
        
    5:  // poll again for response because resource was busy
        #TP_poll(IN := FALSE,
                 PT := T#100ms);
        #RDREC_Function(REQ := FALSE,
                        RECORD := #read);
        #sequencecontrol := 4;  // ... repeat read data record / continue polling   
        
    98: // request done successfully
        #TP_poll(IN := FALSE,
                 PT := T#100ms);
        #RDREC_Function(REQ := FALSE,
                        RECORD := #read);
        IF #REQ = FALSE THEN
            #DONE_VALID := FALSE;
            #BUSY := FALSE;
            #ERROR := FALSE;
            #RD_LEN := INT#0;
            #STATUS := DW#16#00000000;
            #IOL_STATUS := DW#16#00010000; // ready for new request
            #sequencecontrol := 0;
            #typeofrequest := 0;
        ELSE
            ;
        END_IF;
        
    99: // Function aborted with error
        #TP_poll(IN := FALSE,
                 PT := T#100ms);
        #WRREC_Function(REQ := FALSE);
        #RDREC_Function(REQ := FALSE,
                        RECORD := #read);
        #DONE_VALID := FALSE;
        #BUSY := FALSE;
        #RD_LEN := INT#0;
        #sequencecontrol := 0;
        #typeofrequest := 0;
        
    ELSE  // no relevant case, ready for new request
        #WRREC_Function(REQ := FALSE);
        #RDREC_Function(REQ := FALSE,
                        RECORD := #read);
        #TP_poll(IN := FALSE,
                 PT := T#100ms);
        #TON_monitoring(IN := FALSE,
                        PT := T#20s);
        #sequencecontrol := 0;
        #typeofrequest := 0;
END_CASE;


(*---------------------------------------------------------------------------------------------------------------------
            MONITORING
---------------------------------------------------------------------------------------------------------------------*)
#TON_monitoring(IN := #sequencecontrol > 0 AND #sequencecontrol < 98,
                PT := T#20s);
IF #TON_monitoring.Q THEN
    #ERROR := TRUE;
    #IOL_STATUS := DW#16#80000000; // request time out       
    #sequencecontrol := 99; // aborting function with error
END_IF;
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo liebe SPS Freunde,
was ihr da macht siehr recht interessant aus.
Ich (Klaus Loy, Yasakawa, ehemals VIPA) lese hier nur sehr selten mit.
Ein Kollege hat mich auf dieses IO-Link Thema aufmerksam gemacht.
Mich würde die Tool Kommuikation PCT-Tool zu IO-Link Modul auch interessieren.
Bin aber grad S7Comm mässig etwas aus der Übung.

>Verbindungsaufbau geschieht zu TSAP 0xf402, ist das in irgendeiner Weise auf die IO-Link Baugruppe zurückzuführen?

Ich kenne dieses TSAP API Byte, in folger Form:
00: verboten, bzw unüblich
01: PG
02: OP
03: Other, sonstige
04...0F: verboten, bzw unüblich
10...DF: projektierte S7 Verbindungen
E0: offene Communikation TCON
FA: TCI Routing
FD: S7-Basis Kommunikation, Teleservice
FE: KBus Kommunikation, CPU-->CP, SDB-Übertragung

F4: sehe ich auch zum erstenmal, Vermutlich eine spezielle Kennung für das PCT-Tool
Da gibt es dann noch das Stichwort "Datensatz routing" evtl. ist genau diese API KEnnung.

Ich möchte Euerer Diskussion hier weiter folgen.

Hier ein paar Fragen:
Diese PCT-Tool Verbindung geht ja sicherlich zu einer CPU und dann gehen die Datensätze von dort weiter über
Profibus oder Profinet zum entsprechenden "Zielgerät" hab ich das richtig verstanden ?

Wenn ihr z.B. mit diesem netten Python Code Daten hin und her transferiert und da nicht "jeder" Datensatz funktioniert,
dann könnte man das ja am Projebus oder Profinet mit sniffern, welche Fehlermeldung da kommt,
oder ob der entsprechende Datensatz da überhaupt raus geht.

Mehr fällt mir grad nicht zu dem Thema ein, ich werd es aber im Auge behalten.

mfG. K.Loy
 
Das was Siemens da in S7comm eingepackt hat, entspricht so wie ich das bisher gesehen habe dem von mir in #27 verlinkten Standard für Profibus / Profinet zu IO-Link Gateways. Das sind 6 oder 8 Bytes die Siemens noch davor gestellt hat. Ich habe gestern auch ein paar Handbücher zu IO-Link Gateways in Augenschein genommen in denen diese Protokolldetails auch erwähnt werden.

Ein Routing TSAP sieht auf jeden Fall anders aus, der ist länger als 2 Bytes. Er verwendet ja hier auch eine NC-Steuerung, da scheint mir einiges etwas anders zu sein. Da müsste mal jemand mit einer "normalen" CPU und dem PCT eine Aufzeichnung erstellen.
 
Hallo Thomas,

ich meinte keinen Routing TSAP im Sinne von PG --> CPU1 --> Net2 --> CPU2, da ist der SAP richtig lang.
Sondern ich meinte "Datensatz Routing", ich hab grad mal hierzu gegoogelt, ...

Welcher Unterschied besteht zwischen "normalem Routing" und Datensatz-Routing?

Beitrags-ID: 7000978 https://support.industry.siemens.com/cs/document/7000978

In diesem Beitrag findet sich auch folgender Hinweis:
Wenn Sie Daten über über Netzwerkgrenzen hinweg übertragen, verwenden Sie die Funktion "S7-Routing".
Hierbei können Sie Informationen von einem Sender über verschiedene Netzwerke hinweg zu einem Empfänger verschicken.
Weitere Informationen zur Funktion "S7-Routing" finden Sie unter der Beitrags-ID 584459.


Was einen Test mit S7-PCT und Siemens CPUs angeht, könnte ich schon was probieren aber ich hab halt nur eine altes S7-PCT V3.2 von ca. 2013 zur Hand.
Ich weiß nicht ob das aktuell genug ist.

mfG. Klaus Loy
 
Danke für die Info,
ich hab den Download gestern auch gefunden als ich nach einer aktuelleren Version gesucht hatte.
Nun hab ich V3.5 SP1 installiert. Mal schaun was man damit tun kann.
Und was man von der Kommunikation zwischen Tool und CPU sieht.

mfG. K.Loy
 
Ich hab hier mal ein wenig mit dem S7-PCT V3.5 SP1 rum gemacht. Meine Konfig ist in den Screenshots zu sehen.
Leider bekomme ich eine Online Verbindung nur dann hin, wenn der PC/PG direkt mit dem Profinet de PN-Devices verbunden ist.
Dann erfolgt aber eine "Profinet" UDP-Kommunkation mit PN-Datensätzen.
Eine S7-Verbindung durch die CPU hindurch konnte ich nicht zustande bringen. Ich habs auch mit zwei getrennten Netzen versucht.
Aber S7-PCT wollte IMMER nur durekt mit dem PN-Device kommunzieren.
Keine Ahnung, nicht mal wenn Routing einstelle geht es.

IO-Link_Aufbau.jpg
Ich werde später noch Tests mit TIA machen.

mfG. K.Loy
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Kannst du mal mit ner ET200 ProfiBus testen?

Und einen Wireshark der Kommunikation mit der ET200 ProfiNet? PN-Device Kommunikation ist ja auch interessant (PC->ET200->IOL-Master)
 
Hallo Hans54216,
ich denke du hast mich gemeint. Leider habe ich keine Profibus Anschaltung für ET200SP, daher kann ich das nicht testen.
Die Kommunikation S7-PCT --> IOL-Master kann ich gerne aufzeichnen.
Nur ist die Frage, welche Online "Anfragen" soll ich da machen, ich kenn mich zu wenig mit der S7-PCT DSoftware aus.
Ich würde einfach mal auf den IL-Master anklicken und dann Online schalten. Hierzu würde ich dann die Wireshark Aufzeichnung und mein Step7 Projekt posten.
Wäre das so gewünscht ?

Wenn ich noch eine ander "Ansicht" mit schneiden soll, sag mir was und wie.

mfG. K.Loy
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Online Schalten gemacht, sie Screenshot, Wireshark. Kommunikation über Ethernet direkt zu CPU P1, PN-Device hängt an P2,
so dass die PN_IO Telegramme nicht im wireshark enthalten sind.

Und über S7comm / TCP Port 102 geht gar nichts?
So wie ich das sehe sind in den PN-Telegrammen nur die Standard I&M Abfragen enthalten und nichts IOL spezifisches.

In dem Dokument zur IO-Link Integration in Profibus/Profinet ist bei Aufbau eines IOL-Calls nur der DPV1-Header für Profibus aufgelistet, in einer Anmerkung steht dass das auch PN-IO sein kann mit einem entsprechenden PN-IO Header mit API/Slot/Subslot. Alles danach (Call-Header, IOL-Header, Body) findet sich auch beim Transport über S7comm wieder, wenn auch mit abweichenden Längen. Und der DPV1-Header fehlt komplett, oder sieht zumindest komplett anders aus.
 
Hier als Zip.

Code:
      SET   
      SAVE  
      =     L     26.1
      U     #R_TRIG_REQ_old
      NOT   
      U     #REQ
      =     #R_TRIG_REQ
      U     #REQ
      =     #R_TRIG_REQ_old
      L     #sequencecontrol
      L     0
      ==I   
      U     #R_TRIG_REQ
      SPBN  A7d0
      CLR   
      =     #DONE_VALID
      SET   
      =     #BUSY
      CLR   
      =     #ERROR
      L     DW#16#0
      T     #STATUS
      T     #SF_STATUS
      L     L#0
      T     #LENGTH
      T     #segment
      T     #address
      T     #totallength
      U     #RD_WR
      SPBN  A7d1
      L     2
      T     #typeofrequest
      L     DW#16#10022800
      T     LD    32
      L     DIW [AR2,P#22.0]
      T     LW    36
      L     DID [AR2,P#24.0]
      T     LD    38
      L     DW#16#10022800
      T     LD    42
      L     DINO
      T     LW    46
      TAR2  
      +     L#6544
      T     LD    48
      TAR2  LD    28
      UC    SFC   20
            P#L 32.0
            P#L 0.0
            P#L 42.0
      LAR2  LD    28
      L     #RetVal_BLKMOV
      SPA   A7d2
A7d1: L     1
      T     #typeofrequest
      L     0
      T     #i
A7d3: L     #i
      L     10239
      <=I   
      SPBN  A7d2
      L     #i
      ITD   
      L     L#0
      +D    
      L     L#8
      *D    
      TAR2  
      +D    
      L     B#16#0
      TAK   
      LAR1  
      TAK   
      T     DIB [AR1,P#818.0]
      L     #i
      L     1
      +I    
      T     #i
      SPA   A7d3
A7d2: L     1
      T     #sequencecontrol
      SPA   A7d5
A7d0: CLR   
A7d5: L     #sequencecontrol
      L     1
      TAK   
      ==I   
      T     LW    32
      SPB   A7d7
      SPA   A7d8
A7d7: L     B#16#1
      T     #rec.reset.ExtendedFunctionNum
      L     DW#16#FFFFFFFF
      T     #rec.reset.SequenceNo
      L     DW#16#FF
      T     #STATUS
      L     2
      T     #sequencecontrol
      SPA   A7d6
A7d8: L     2
      L     LW    32
      ==I   
      SPB   A7d9
      SPA   A7da
A7d9: SET   
      =     #WRREC_Function.REQ
      L     #ID
      T     #WRREC_Function.ID
      L     #index
      T     #WRREC_Function.INDEX
      L     6
      T     #WRREC_Function.LEN
      L     DW#16#100200F0
      T     DID [AR2,P#72.0]
      L     DINO
      T     DIW [AR2,P#76.0]
      TAR2  
      +     L#784
      T     DID [AR2,P#78.0]
      +AR2  P#56.0
      UC    SFB   53
      +AR2  P#8136.0
      U     #WRREC_Function.DONE
      =     #wrrec_if.done
      U     #WRREC_Function.BUSY
      =     #wrrec_if.busy
      U     #WRREC_Function.ERROR
      =     #wrrec_if.error
      L     #WRREC_Function.STATUS
      T     #wrrec_if.status
      U     #wrrec_if.done
      SPBN  A7db
      L     #wrrec_if.status
      T     #SF_STATUS
      L     3
      T     #sequencecontrol
      SPA   A7d6
A7db: CLR   
      U     #wrrec_if.error
      L     #rdrec_if.status
      L     DW#16#DF80B000
      =     L     26.2
      ==D   
      U     L     26.2
      SPBN  A7dd
      SET   
      =     #ERROR
      L     DW#16#30000
      T     #STATUS
      L     #rdrec_if.status
      T     #SF_STATUS
      L     99
      T     #sequencecontrol
      SPA   A7d6
A7dd: CLR   
      U     #wrrec_if.error
      SPBN  A7de
      SET   
      =     #ERROR
      L     DW#16#30000
      T     #STATUS
      L     #wrrec_if.status
      T     #SF_STATUS
      L     #sequencecontrol
      T     #errorTrigger
      L     99
      T     #sequencecontrol
      SPA   A7d6
A7de: SPA   A7d6
A7da: L     3
      L     LW    32
      ==I   
      SPB   A7df
      SPA   A7e0
A7df: CLR   
      =     #WRREC_Function.REQ
      L     #ID
      T     #WRREC_Function.ID
      L     #index
      T     #WRREC_Function.INDEX
      L     6
      T     #WRREC_Function.LEN
      L     DW#16#100200F0
      T     DID [AR2,P#72.0]
      L     DINO
      T     DIW [AR2,P#76.0]
      TAR2  
      +     L#784
      T     DID [AR2,P#78.0]
      +AR2  P#56.0
      UC    SFB   53
      +AR2  P#8136.0
      U     #WRREC_Function.DONE
      =     #wrrec_if.done
      U     #WRREC_Function.BUSY
      =     #wrrec_if.busy
      U     #WRREC_Function.ERROR
      =     #wrrec_if.error
      L     #WRREC_Function.STATUS
      T     #wrrec_if.status
      U     #wrrec_if.done
      NOT   
      SPBN  A7e1
      L     DW#16#FF
      T     #STATUS
      L     4
      T     #sequencecontrol
      SPA   A7d6
A7e1: CLR   
      U     #wrrec_if.error
      SPBN  A7e3
      SET   
      =     #ERROR
      L     #wrrec_if.status
      T     #SF_STATUS
      L     #sequencecontrol
      T     #errorTrigger
      L     99
      T     #sequencecontrol
      SPA   A7d6
A7e3: SPA   A7d6
A7e0: L     4
      L     LW    32
      ==I   
      SPB   A7e4
      SPA   A7e5
A7e4: L     #typeofrequest
      L     1
      ==I   
      SPBN  A7e6
      L     DW#16#100FF
      T     #STATUS
      L     10
      T     #sequencecontrol
      SPA   A7d6
A7e6: L     #typeofrequest
      L     2
      ==I   
      SPBN  A7e8
      L     DW#16#200FF
      T     #STATUS
      L     20
      T     #sequencecontrol
      SPA   A7d6
A7e8: SET   
      =     #ERROR
      L     DW#16#300FF
      T     #STATUS
      L     #sequencecontrol
      T     #errorTrigger
      L     99
      T     #sequencecontrol
      SPA   A7d6
A7e5: L     10
      L     LW    32
      ==I   
      SPB   A7e9
      SPA   A7ea
A7e9: SET   
      =     #RDREC_Function.REQ
      L     #ID
      T     #RDREC_Function.ID
      L     #index
      T     #RDREC_Function.INDEX
      L     240
      T     #RDREC_Function.MLEN
      L     DW#16#100200F0
      T     DID [AR2,P#46.0]
      L     DINO
      T     DIW [AR2,P#50.0]
      TAR2  
      +     L#2704
      T     DID [AR2,P#52.0]
      +AR2  P#28.0
      UC    SFB   52
      +AR2  P#8164.0
      U     #RDREC_Function.VALID
      =     #rdrec_if.valid
      U     #RDREC_Function.BUSY
      =     #rdrec_if.busy
      U     #RDREC_Function.ERROR
      =     #rdrec_if.error
      L     #RDREC_Function.STATUS
      T     #rdrec_if.status
      L     #RDREC_Function.LEN
      T     #rdrec_if.length
      U     #rdrec_if.valid
      SPBN  A7eb
      L     #rdrec_if.length
      L     6
      >I    
      L     #rec.backup.ExtendedFunctionNum
      L     B#16#2
      =     L     26.2
      ==I   
      U     L     26.2
      SPBN  A7ec
      L     DW#16#10000
      L     #rec.backup.SequenceNo
      OD    
      T     #STATUS
      L     #rdrec_if.status
      T     #SF_STATUS
      L     #rec.backup.SequenceNo
      T     #segment
      L     #rdrec_if.length
      L     6
      -I    
      T     #tmplength
      L     DW#16#100200EA
      T     LD    34
      L     DINO
      T     LW    38
      TAR2  
      +     L#2752
      T     LD    40
      L     LD    34
      T     LD     4
      L     LD    38
      T     LD     8
      L     LW    42
      T     LW    12
      L     #tmplength
      T     #ANYsource.length
      L     #address
      L     L#0
      +D    
      L     L#8
      *D    
      TAR2  
      +D    
      LAR1  
      L     DIB [AR1,P#818.0]
      TAK   
      T     LD    44
      TAK   
      L     DW#16#10020001
      T     LD    34
      L     DINO
      T     LW    38
      L     LD    44
      +     L#6544
      OD    DW#16#84000000
      T     LD    40
      L     LD    34
      T     LD    14
      L     LD    38
      T     LD    18
      L     LW    42
      T     LW    22
      L     #tmplength
      T     #ANYdestination.length
      L     LD     4
      T     LD    34
      L     LD     8
      T     LD    38
      L     LW    12
      T     LW    42
      L     LD    14
      T     LD    48
      L     LD    18
      T     LD    52
      L     LW    22
      T     LW    56
      TAR2  LD    28
      UC    SFC   20
            P#L 34.0
            P#L 0.0
            P#L 48.0
      LAR2  LD    28
      L     #RetVal_BLKMOV
      L     #RetVal_BLKMOV
      L     0
      <>I   
      SPBN  A7ed
      SET   
      =     #ERROR
      L     DW#16#110FF
      T     #STATUS
      L     #RetVal_BLKMOV
      UD    DW#16#FFFF
      T     #SF_STATUS
      L     99
      T     #sequencecontrol
      SPA   A7ee
A7ed: CLR   
A7ee: L     #tmplength
      ITD   
      L     #totallength
      +D    
      T     #totallength
      L     #tmplength
      ITD   
      L     #address
      +D    
      T     #address
      SPA   A7d6
A7ec: L     #rdrec_if.length
      L     6
      ==I   
      SPBN  A7f0
      L     DW#16#10022800
      T     LD    34
      L     DINO
      T     LW    38
      TAR2  
      +     L#6544
      T     LD    40
      L     LD    34
      T     LD     4
      L     LD    38
      T     LD     8
      L     LW    42
      T     LW    12
      L     W#16#2800
      T     #ANYsource.length
      L     DW#16#10022800
      T     LD    34
      L     DIW [AR2,P#22.0]
      T     LW    38
      L     DID [AR2,P#24.0]
      T     LD    40
      L     LD    34
      T     LD    14
      L     LD    38
      T     LD    18
      L     LW    42
      T     LW    22
      L     W#16#2800
      T     #ANYdestination.length
      L     LD     4
      T     LD    34
      L     LD     8
      T     LD    38
      L     LW    12
      T     LW    42
      L     LD    14
      T     LD    48
      L     LD    18
      T     LD    52
      L     LW    22
      T     LW    56
      TAR2  LD    28
      UC    SFC   20
            P#L 34.0
            P#L 0.0
            P#L 48.0
      LAR2  LD    28
      L     #RetVal_BLKMOV
      L     #RetVal_BLKMOV
      L     0
      <>I   
      SPBN  A7f1
      SET   
      =     #ERROR
      L     DW#16#110FF
      T     #STATUS
      L     #RetVal_BLKMOV
      UD    DW#16#FFFF
      T     #SF_STATUS
      L     99
      T     #sequencecontrol
      SPA   A7f2
A7f1: CLR   
A7f2: SET   
      =     #DONE_VALID
      CLR   
      =     #BUSY
      =     #ERROR
      L     DW#16#10000
      L     #rec.backup.SequenceNo
      OD    
      T     #STATUS
      L     #rdrec_if.status
      T     #SF_STATUS
      L     #totallength
      T     #LENGTH
      L     11
      T     #sequencecontrol
      SPA   A7d6
A7f0: SPA   A7d6
A7eb: CLR   
      U     #rdrec_if.error
      SPBN  A7f4
      CLR   
      =     #DONE_VALID
      =     #BUSY
      SET   
      =     #ERROR
      L     #rdrec_if.status
      T     #SF_STATUS
      L     #rdrec_if.length
      ITD   
      T     #LENGTH
      L     #sequencecontrol
      T     #errorTrigger
      L     99
      T     #sequencecontrol
      SPA   A7d6
A7f4: SPA   A7d6
A7ea: L     11
      L     LW    32
      ==I   
      SPB   A7f5
      SPA   A7f6
A7f5: CLR   
      =     #RDREC_Function.REQ
      L     #ID
      T     #RDREC_Function.ID
      L     #index
      T     #RDREC_Function.INDEX
      L     240
      T     #RDREC_Function.MLEN
      L     DW#16#100200F0
      T     DID [AR2,P#46.0]
      L     DINO
      T     DIW [AR2,P#50.0]
      TAR2  
      +     L#2704
      T     DID [AR2,P#52.0]
      +AR2  P#28.0
      UC    SFB   52
      +AR2  P#8164.0
      U     #RDREC_Function.VALID
      =     #rdrec_if.valid
      U     #RDREC_Function.BUSY
      =     #rdrec_if.busy
      U     #RDREC_Function.ERROR
      =     #rdrec_if.error
      L     #RDREC_Function.STATUS
      T     #rdrec_if.status
      L     #RDREC_Function.LEN
      T     #rdrec_if.length
      U     #rdrec_if.valid
      NOT   
      SPBN  A7f7
      L     98
      T     #sequencecontrol
      SPA   A7d6
A7f7: CLR   
      U     #rdrec_if.error
      SPBN  A7f9
      CLR   
      =     #DONE_VALID
      =     #BUSY
      SET   
      =     #ERROR
      L     #rdrec_if.status
      T     #SF_STATUS
      L     #rdrec_if.length
      ITD   
      T     #LENGTH
      L     #sequencecontrol
      T     #errorTrigger
      L     99
      T     #sequencecontrol
      SPA   A7d6
A7f9: SPA   A7d6
A7f6: L     20
      L     LW    32
      ==I   
      SPB   A7fa
      SPA   A7fb
A7fa: L     B#16#1
      T     #rec.restore.ExtendedFunctionNum
      L     #segment
      T     #rec.restore.SequenceNo
      L     DW#16#20000
      L     #rec.restore.SequenceNo
      OD    
      T     #STATUS
      L     #address
      L     L#0
      +D    
      L     L#8
      *D    
      TAR2  
      +D    
      LAR1  
      L     DIB [AR1,P#818.0]
      TAK   
      T     LD    48
      TAK   
      L     DW#16#10020001
      T     LD    34
      L     DINO
      T     LW    38
      L     LD    48
      +     L#6544
      OD    DW#16#84000000
      T     LD    40
      L     LD    34
      T     LD     4
      L     LD    38
      T     LD     8
      L     LW    42
      T     LW    12
      L     W#16#EA
      T     #ANYsource.length
      L     DW#16#100200EA
      T     LD    34
      L     DINO
      T     LW    38
      TAR2  
      +     L#4672
      T     LD    40
      L     LD    34
      T     LD    14
      L     LD    38
      T     LD    18
      L     LW    42
      T     LW    22
      L     W#16#EA
      T     #ANYdestination.length
      L     LD     4
      T     LD    34
      L     LD     8
      T     LD    38
      L     LW    12
      T     LW    42
      L     LD    14
      T     LD    52
      L     LD    18
      T     LD    56
      L     LW    22
      T     LW    60
      TAR2  LD    28
      UC    SFC   20
            P#L 34.0
            P#L 0.0
            P#L 52.0
      LAR2  LD    28
      L     #RetVal_BLKMOV
      L     #RetVal_BLKMOV
      L     0
      <>I   
      SPBN  A7fc
      SET   
      =     #ERROR
      L     #RetVal_BLKMOV
      UD    DW#16#FFFF
      T     #SF_STATUS
      L     99
      T     #sequencecontrol
      SPA   A7d6
A7fc: L     21
      T     #sequencecontrol
      SPA   A7d6
A7fb: L     21
      L     LW    32
      ==I   
      SPB   A7fe
      SPA   A7ff
A7fe: SET   
      =     #WRREC_Function.REQ
      L     #ID
      T     #WRREC_Function.ID
      L     #index
      T     #WRREC_Function.INDEX
      L     240
      T     #WRREC_Function.LEN
      L     DW#16#100200F0
      T     DID [AR2,P#72.0]
      L     DINO
      T     DIW [AR2,P#76.0]
      TAR2  
      +     L#4624
      T     DID [AR2,P#78.0]
      +AR2  P#56.0
      UC    SFB   53
      +AR2  P#8136.0
      U     #WRREC_Function.DONE
      =     #wrrec_if.done
      U     #WRREC_Function.BUSY
      =     #wrrec_if.busy
      U     #WRREC_Function.ERROR
      =     #wrrec_if.error
      L     #WRREC_Function.STATUS
      T     #wrrec_if.status
      U     #wrrec_if.done
      SPBN  A800
      L     #totallength
      L     L#234
      +D    
      T     #totallength
      L     #wrrec_if.status
      T     #SF_STATUS
      L     22
      T     #sequencecontrol
      SPA   A7d6
A800: CLR   
      U     #wrrec_if.error
      SPBN  A802
      SET   
      =     #ERROR
      L     #wrrec_if.status
      T     #SF_STATUS
      L     #sequencecontrol
      T     #errorTrigger
      L     99
      T     #sequencecontrol
      SPA   A7d6
A802: SPA   A7d6
A7ff: L     22
      L     LW    32
      ==I   
      SPB   A803
      SPA   A804
A803: CLR   
      =     #WRREC_Function.REQ
      L     #ID
      T     #WRREC_Function.ID
      L     #index
      T     #WRREC_Function.INDEX
      L     240
      T     #WRREC_Function.LEN
      L     DW#16#100200F0
      T     DID [AR2,P#72.0]
      L     DINO
      T     DIW [AR2,P#76.0]
      TAR2  
      +     L#4624
      T     DID [AR2,P#78.0]
      +AR2  P#56.0
      UC    SFB   53
      +AR2  P#8136.0
      U     #WRREC_Function.DONE
      =     #wrrec_if.done
      U     #WRREC_Function.BUSY
      =     #wrrec_if.busy
      U     #WRREC_Function.ERROR
      =     #wrrec_if.error
      L     #WRREC_Function.STATUS
      T     #wrrec_if.status
      U     #wrrec_if.done
      NOT   
      SPBN  A805
      L     #wrrec_if.status
      T     #SF_STATUS
      L     23
      T     #sequencecontrol
      SPA   A7d6
A805: CLR   
      U     #wrrec_if.error
      SPBN  A807
      SET   
      =     #ERROR
      L     #wrrec_if.status
      T     #SF_STATUS
      L     #sequencecontrol
      T     #errorTrigger
      L     99
      T     #sequencecontrol
      SPA   A7d6
A807: SPA   A7d6
A804: L     23
      L     LW    32
      ==I   
      SPB   A808
      SPA   A809
A808: SET   
      =     #RDREC_Function.REQ
      L     #ID
      T     #RDREC_Function.ID
      L     #index
      T     #RDREC_Function.INDEX
      L     240
      T     #RDREC_Function.MLEN
      L     DW#16#100200F0
      T     DID [AR2,P#46.0]
      L     DINO
      T     DIW [AR2,P#50.0]
      TAR2  
      +     L#2704
      T     DID [AR2,P#52.0]
      +AR2  P#28.0
      UC    SFB   52
      +AR2  P#8164.0
      U     #RDREC_Function.VALID
      =     #rdrec_if.valid
      U     #RDREC_Function.BUSY
      =     #rdrec_if.busy
      U     #RDREC_Function.ERROR
      =     #rdrec_if.error
      L     #RDREC_Function.STATUS
      T     #rdrec_if.status
      L     #RDREC_Function.LEN
      T     #rdrec_if.length
      U     #rdrec_if.valid
      L     #rec.backup.ExtendedFunctionNum
      L     B#16#2
      =     L     26.2
      ==I   
      U     L     26.2
      SPBN  A80a
      L     #rec.backup.SequenceNo
      L     DW#16#FFFFFF01
      ==D   
      SPBN  A80b
      L     #segment
      L     L#1
      +D    
      T     #segment
      L     #address
      L     L#234
      +D    
      T     #address
      L     DW#16#FFFFFF01
      T     #STATUS
      L     24
      T     #sequencecontrol
      SPA   A7d6
A80b: L     #rec.backup.SequenceNo
      L     DW#16#FFFFFF02
      ==D   
      SPBN  A80d
      L     #segment
      L     L#1
      +D    
      T     #segment
      L     #address
      L     L#234
      +D    
      T     #address
      L     DW#16#FFFFFF02
      T     #STATUS
      L     24
      T     #sequencecontrol
      SPA   A7d6
A80d: L     #rec.backup.SequenceNo
      L     DW#16#FFFFFF03
      ==D   
      SPBN  A80e
      T     #STATUS
      L     25
      T     #sequencecontrol
      SPA   A7d6
A80e: L     #rec.backup.SequenceNo
      L     DW#16#FFFFFF04
      ==D   
      SPBN  A80f
      SET   
      =     #ERROR
      T     #STATUS
      L     99
      T     #sequencecontrol
      SPA   A7d6
A80f: L     #rec.backup.SequenceNo
      L     DW#16#FFFFFF05
      ==D   
      SPBN  A810
      SET   
      =     #ERROR
      T     #STATUS
      L     99
      T     #sequencecontrol
      SPA   A7d6
A810: L     #rec.backup.SequenceNo
      L     DW#16#FFFFFF06
      ==D   
      SPBN  A811
      SET   
      =     #ERROR
      T     #STATUS
      L     99
      T     #sequencecontrol
      SPA   A7d6
A811: L     #rec.backup.SequenceNo
      L     DW#16#FFFFFF07
      ==D   
      SPBN  A812
      SET   
      =     #ERROR
      T     #STATUS
      L     99
      T     #sequencecontrol
      SPA   A7d6
A812: SPA   A7d6
A80a: CLR   
      U     #rdrec_if.error
      SPBN  A814
      SET   
      =     #ERROR
      L     #rdrec_if.status
      T     #SF_STATUS
      L     #sequencecontrol
      T     #errorTrigger
      L     99
      T     #sequencecontrol
      SPA   A7d6
A814: SPA   A7d6
A809: L     24
      L     LW    32
      ==I   
      SPB   A815
      SPA   A816
A815: CLR   
      =     #RDREC_Function.REQ
      L     #ID
      T     #RDREC_Function.ID
      L     #index
      T     #RDREC_Function.INDEX
      L     240
      T     #RDREC_Function.MLEN
      L     DW#16#100200F0
      T     DID [AR2,P#46.0]
      L     DINO
      T     DIW [AR2,P#50.0]
      TAR2  
      +     L#2704
      T     DID [AR2,P#52.0]
      +AR2  P#28.0
      UC    SFB   52
      +AR2  P#8164.0
      U     #RDREC_Function.VALID
      =     #rdrec_if.valid
      U     #RDREC_Function.BUSY
      =     #rdrec_if.busy
      U     #RDREC_Function.ERROR
      =     #rdrec_if.error
      L     #RDREC_Function.STATUS
      T     #rdrec_if.status
      L     #RDREC_Function.LEN
      T     #rdrec_if.length
      U     #rdrec_if.valid
      NOT   
      SPBN  A817
      L     20
      T     #sequencecontrol
      SPA   A7d6
A817: CLR   
      U     #rdrec_if.error
      SPBN  A819
      SET   
      =     #ERROR
      L     #rdrec_if.status
      T     #SF_STATUS
      L     #sequencecontrol
      T     #errorTrigger
      L     99
      T     #sequencecontrol
      SPA   A7d6
A819: SPA   A7d6
A816: L     25
      L     LW    32
      ==I   
      SPB   A81a
      SPA   A81b
A81a: CLR   
      =     #RDREC_Function.REQ
      L     #ID
      T     #RDREC_Function.ID
      L     #index
      T     #RDREC_Function.INDEX
      L     240
      T     #RDREC_Function.MLEN
      L     DW#16#100200F0
      T     DID [AR2,P#46.0]
      L     DINO
      T     DIW [AR2,P#50.0]
      TAR2  
      +     L#2704
      T     DID [AR2,P#52.0]
      +AR2  P#28.0
      UC    SFB   52
      +AR2  P#8164.0
      U     #RDREC_Function.VALID
      =     #rdrec_if.valid
      U     #RDREC_Function.BUSY
      =     #rdrec_if.busy
      U     #RDREC_Function.ERROR
      =     #rdrec_if.error
      L     #RDREC_Function.STATUS
      T     #rdrec_if.status
      L     #RDREC_Function.LEN
      T     #rdrec_if.length
      U     #rdrec_if.valid
      NOT   
      SPBN  A81c
      SET   
      =     #DONE_VALID
      CLR   
      =     #BUSY
      =     #ERROR
      L     #rdrec_if.status
      T     #SF_STATUS
      L     #totallength
      T     #LENGTH
      L     98
      T     #sequencecontrol
      SPA   A7d6
A81c: CLR   
      U     #rdrec_if.error
      SPBN  A81e
      SET   
      =     #ERROR
      L     #rdrec_if.status
      T     #SF_STATUS
      L     #sequencecontrol
      T     #errorTrigger
      L     99
      T     #sequencecontrol
      SPA   A7d6
A81e: SPA   A7d6
A81b: L     98
      L     LW    32
      ==I   
      SPB   A81f
      SPA   A820
A81f: CLR   
      =     #RDREC_Function.REQ
      L     DW#16#100200F0
      T     DID [AR2,P#46.0]
      L     DINO
      T     DIW [AR2,P#50.0]
      TAR2  
      +     L#2704
      T     DID [AR2,P#52.0]
      +AR2  P#28.0
      UC    SFB   52
      +AR2  P#8164.0
      CLR   
      =     #WRREC_Function.REQ
      +AR2  P#56.0
      UC    SFB   53
      +AR2  P#8136.0
      U     #REQ
      NOT   
      SPBN  A7d6
      CLR   
      =     #DONE_VALID
      L     DW#16#0
      T     #STATUS
      T     #SF_STATUS
      L     L#0
      T     #LENGTH
      L     0
      T     #sequencecontrol
      T     #typeofrequest
      SPA   A7d6
A820: L     99
      L     LW    32
      ==I   
      SPB   A822
      SPA   A823
A822: CLR   
      =     #RDREC_Function.REQ
      L     DW#16#100200F0
      T     DID [AR2,P#46.0]
      L     DINO
      T     DIW [AR2,P#50.0]
      TAR2  
      +     L#2704
      T     DID [AR2,P#52.0]
      +AR2  P#28.0
      UC    SFB   52
      +AR2  P#8164.0
      CLR   
      =     #WRREC_Function.REQ
      +AR2  P#56.0
      UC    SFB   53
      +AR2  P#8136.0
      CLR   
      =     #DONE_VALID
      =     #BUSY
      L     L#0
      T     #LENGTH
      L     0
      T     #sequencecontrol
      T     #typeofrequest
      SPA   A7d6
A823: CLR   
A7d6: CLR   
      U     L     26.1
      SAVE  
      BE

Es ist doch hoffentlich nicht dein Ernst. Es gibt doch eine offizielle Quelle für diesen Baustein.
 
Du hast bei deiner AWL-Quelle vermutlich den IO_LINK_MASTER gepostet, von dem liefert Siemens auch die SCL-Quelle mit.

Wenn man aber in den IO_LINK_DEVICE reinschaut, dann sieht man zumindest in den STAT-Variablen in der Struct "read.header" den Aufbau des Datenteils das auch übers Netzwerk geht. Glücklicherweise mit Kommentar :) Leider fehlt hier die SCL-Quelle, müsste man sich anfertigen wenn das weiterhilft.

Doch, die gibt es. Muß man halt woanders schauen, nicht im Beitrag zu dem Baustein. Aber die ist veröffentlicht. Von der Firma Siemens, liebe Moderation, nicht von slowakischen Hackern.
 
Zurück
Oben