Step 7 Vorschlag für Error-Handling mit WinCC-Fehlerauswertung/-anzeige & Einzelquitt.

logo78

Level-1
Beiträge
84
Reaktionspunkte
4
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich musste für einen Kunden das 'Fehlerhandling' vereinheitlichen und habe mir lange den Kopf darüber zerbrochen.
Entstanden sind drei Funktionen und zwei Excel-Tabellen, mit der man das Anlegen, Quittieren, Einzelquittieren,
In-und Exportiereren von Fehlermeldungen relativ komfortabel erledigen kann.

Schaut euch das 18minütige Video an.
War schon fast mehr Arbeit als wie das Ausdenken und Umsetzen des Codes :rolleyes:
1.png

2.png

3.png

Das Ergebnis ist sicherlich nicht der Weisheits letzter Schluss und ausbaufähig.
Es ist in AWL programmiert und ist mit Zeilenkommentaren versehen.
Vllt hilft es dem einen oder anderen. Wiederverwendung, Verbesserung ist explizit erwünscht.
Oder falls Jemand noch Anwendungsbeispiele 'Any, AR1, AR2, Loop, etc...' braucht - hier findet ihr alles :ROFLMAO:

Da nicht alles auf dem 1.Blick ersichtlich ist, habe ich mir auch erlaubt Video zu erstellen.
Hier wird die Funktion, der Aufbau bishin zur Simulation mit PLCsim erklärt.


Ich hätte das Demo-Projekt hochgeladen. Allerdings verpfuscht Siemens alle möglichen
Stellen im Projekt mit personen-und firmenbezogenen Angaben.

Darum müssen AWL-Quellen und das Video ausreichen ;)

Hochgeladen habe ich das Packet bestehend aus drei AWL-Quellen, ExcelTabellen und ein Video
auf mega.nz... mir ist auf die schnelle kein besserer Filehoster eingefallen.
https://mega.nz/#F!xJcXARLT!YykSh7HUorCOcAbCYdIN9Q

Viel Spass. Feedback/Kritik ist erwünscht :)

Edit: Die exportierten AWL Quellen befinden sich auf dem Hoster.
Falls Jemand Hoster nicht mag, hier sind sie auch...

Code:
FUNCTION "1_MoveFaultsToHMI" : VoidTITLE = Verodere Ext. Quittierbits mit Fehlermeldungen und schiebe es zum HMI-Array
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
   VAR_INPUT 
      iResPLC : Bool;   // Internal/Global reset request from PLC
      iResExt : Bool;   // Internal/Global reset request from external
      iFaults : Any;   // Pointer for the source of all faults
      iExtResets : Any;   // Pointer for the source of the external request requests
      qHMITrigArray : Any;   // Pointer for the destination HMI array, where the faults and the reset requests are stored
   END_VAR


   VAR_OUTPUT 
      qResExt : Bool;   // Collective reset from external
      qfault : Bool;   // fault: target array is not large enough
   END_VAR


   VAR_TEMP 
      hexFF : Byte;   // local 'constant' with B#16#FF
      hex00 : Byte;   // local 'constant' with B#16#00
      loop01 : Int;   // loop counter
      retval : Int;   // just return value, for some 'calls'
      tFaults : Struct   // splitted any pointer
         "10h" : Byte;
         DataType : Byte;
         repetition : Int;
         db_no : Int;
         adres : DWord;
      END_STRUCT;
      tExtResets : Struct   // splitted any pointer
         "10h" : Byte;
         DataType : Byte;
         repetition : Int;
         db_no : Int;
         adres : DWord;
      END_STRUCT;
      tHMITrigArray : Struct   // splitted any pointer
         "10h" : Byte;
         DataType : Byte;
         repetition : Int;
         db_no : Int;
         adres : DWord;
      END_STRUCT;
      WorkAnySource : Any;   // Any pointer for the 'source'
      WorkAnyTarget : Any;   // Any pointer for the 'destination'
      StartAdress2ndHalfTarget : DWord;   // adres-pointer for the 2nd half of the destination
   END_VAR




BEGIN
NETWORK
TITLE = Lokaldaten initialisieren
      L b#16#0;
      T #hex00;
      L b#16#ff;
      T #hexFF;
NETWORK
TITLE = Eingänge 'zerlegen' und in Lokaldaten kopieren
//###Split SourceAny into local data
//copy any pointer of source into AR1
      L P##iFaults;
      LAR1;
//copy any pointer of target into AR2
      LAR2 P##tFaults;
//1st bytes is always 10h for s7
      L B[ AR1, P#0.0];
      T B[ AR2, P#0.0];
//copy data type
      L B[ AR1, P#1.0];
      T B[ AR2, P#1.0];
//copy repetition factor
      L W[ AR1, P#2.0];
      T W[ AR2, P#2.0];
//copy db number
      L W[ AR1, P#4.0];
      T W[ AR2, P#4.0];
//copy pointer (start adres)
      L D[ AR1, P#6.0];
      T D[ AR2, P#6.0];
//################################################


//###Split SourceAny into local data
//copy any pointer of source into AR1
      L P##iExtResets;
      LAR1;
//copy any pointer of target into AR2
      LAR2 P##tExtResets;
//1st bytes is always 10h for s7
      L B[ AR1, P#0.0];
      T B[ AR2, P#0.0];
//copy data type
      L B[ AR1, P#1.0];
      T B[ AR2, P#1.0];
//copy repetition factor
      L W[ AR1, P#2.0];
      T W[ AR2, P#2.0];
//copy db number
      L W[ AR1, P#4.0];
      T W[ AR2, P#4.0];
//copy pointer (start adres)
      L D[ AR1, P#6.0];
      T D[ AR2, P#6.0];
//################################################


//###Split SourceAny into local data
//copy any pointer of source into AR1
      L P##qHMITrigArray;
      LAR1;
//copy any pointer of target into AR2
      LAR2 P##tHMITrigArray;
//1st bytes is always 10h for s7
      L B[ AR1, P#0.0];
      T B[ AR2, P#0.0];
//copy data type
      L B[ AR1, P#1.0];
      T B[ AR2, P#1.0];
//copy repetition factor
      L W[ AR1, P#2.0];
      T W[ AR2, P#2.0];
//copy db number
      L W[ AR1, P#4.0];
      T W[ AR2, P#4.0];
//copy pointer (start adres)
      L D[ AR1, P#6.0];
      T D[ AR2, P#6.0];
//################################################
NETWORK
TITLE = Prüfen ob das Zielfach ausreichen groß ist
//load source byte length and multiply by 2
//reason: in the target array, the first half are the triggers
//        the 2nd half will be the reset bits through the hmi
//        Hence, the destination array must have the double size
//        of the source.
//load source
      L #tFaults.repetition;
      L 2;
      *I;
//load destination
      L #tHMITrigArray.repetition;
//if the source is bigger than the destination = fault
      >I;
      = #qfault;
//if we have a fault, no further processment is required
//programming error
      BEC;
NETWORK
TITLE = Kopiere 1.Hälfte in Ziel-Array: Fehlermeldungen
//build a temporary anypointer for the SOURCE
      LAR1 P##WorkAnySource;
      L #tFaults."10h";
      T B[ AR1, P#0.0];
      L #tFaults.DataType;
      T B[ AR1, P#1.0];
      L #tFaults.repetition;
      T W[ AR1, P#2.0];
      L #tFaults.db_no;
      T W[ AR1, P#4.0];
      L #tFaults.adres;
      T D[ AR1, P#6.0];
//build a temporary anypointer for the DESTINATION
      LAR1 P##WorkAnyTarget;
      L #tHMITrigArray."10h";
      T B[ AR1, P#0.0];
      L #tHMITrigArray.DataType;
      T B[ AR1, P#1.0];
      L #tHMITrigArray.repetition;
      T W[ AR1, P#2.0];
      L #tHMITrigArray.db_no;
      T W[ AR1, P#4.0];
      L #tHMITrigArray.adres;
      T D[ AR1, P#6.0];


//just copy data now
      CALL BLKMOV
      {blk_type := 'Variant'}
      (  SRCBLK                      := #WorkAnySource , 
         RET_VAL                     := #retval , 
         DSTBLK                      := #WorkAnyTarget
      );
NETWORK
TITLE = Kopiere 2.Hälfte in Ziel-Array: Fehlermeldungen - bei Reset PLC oder EXT Zielbereich mit FF überschreiben
//build a temporary anypointer for the SOURCE
      LAR1 P##WorkAnySource;
      L #tExtResets."10h";
      T B[ AR1, P#0.0];
      L #tExtResets.DataType;
      T B[ AR1, P#1.0];
      L #tExtResets.repetition;
      T W[ AR1, P#2.0];
      L #tExtResets.db_no;
      T W[ AR1, P#4.0];
      L #tExtResets.adres;
      T D[ AR1, P#6.0];


//#################################################################
//before we build the DESTINATION Array,
//we must correct/adapt the start adress.
//as described in a previous network, the external
//reset requests has to be placed into the 2nd half of 
//the target array.


//take the length (repition factor)
      L #tHMITrigArray.repetition;
//divide by 2 (=the half)
      L 2;
      /I;
//multiply by 8, to get the right format (bitwise adresing)
      SLD 3;
//start adres is calculated right now
//we should also take the memory area from the origin any pointer
      L #tHMITrigArray.adres;
//take only the lowest byte
//wordwise OR accu1 (memory area) with accu2 (calculated start adres)
      OD;
//save for later usage
      T #StartAdress2ndHalfTarget;
//#################################################################


//build a temporary anypointer for the DESTINATION
      LAR1 P##WorkAnyTarget;
      L #tHMITrigArray."10h";
      T B[ AR1, P#0.0];
      L #tHMITrigArray.DataType;
      T B[ AR1, P#1.0];
      L #tHMITrigArray.repetition;
      T W[ AR1, P#2.0];
      L #tHMITrigArray.db_no;
      T W[ AR1, P#4.0];
//take the previously calculated start adres for the 2nd half of 
//destination array
      L #StartAdress2ndHalfTarget;
      T D[ AR1, P#6.0];


//just copy data now
      CALL BLKMOV
      {blk_type := 'Variant'}
      (  SRCBLK                      := #WorkAnySource , 
         RET_VAL                     := #retval , 
         DSTBLK                      := #WorkAnyTarget
      );


//#################################################################
//if there is PLC or External reset request fill the whole destination
//area with B#16#FF
//We are going to fill only the area, which is neccessary.
//This is the reason, why we are calculation the destination pointer again


      O #iResPLC;
      O #iResExt;
      JCN nofi;


//build a temporary anypointer for the DESTINATION
      LAR1 P##WorkAnyTarget;
      L #tHMITrigArray."10h";
      T B[ AR1, P#0.0];
      L #tHMITrigArray.DataType;
      T B[ AR1, P#1.0];
//instead of the length of the destination area (is longer than source)
//we will use the length of source...we make sure, that we are only
//filling/initialising the are, which is neccessary.
//      L     #tAnyHMITrigArray.repetition
      L #tExtResets.repetition;
      T W[ AR1, P#2.0];
      L #tHMITrigArray.db_no;
      T W[ AR1, P#4.0];
//take the previously calculated start adres for the 2nd half of 
//destination array
      L #StartAdress2ndHalfTarget;
      T D[ AR1, P#6.0];


      CALL FILL
      {ptr_type := 'Variant'}
      (  BVAL                        := #hexFF , 
         RET_VAL                     := #retval , 
         BLK                         := #WorkAnyTarget
      );


nofi:      NOP 0;
NETWORK
TITLE = Prüfe ob irgendeine Reset-Anforderung von Extern anliegt und baue ein 'collective_reset' daraus
//initialise the local bool, for evaluating if any external reset is existent
      CLR;
      = #qResExt;


//here we are going to check, if there is any reset request existent from 
//the external source... this will be done by a loop
//we are going to 'scan' the external requests requests bytewise


//as first, open the corresponding data block, where the information is stored
      OPN DB[ #tExtResets.db_no];


//load the adres pointer into AR1
      LAR1 #tExtResets.adres;
//the length (in bytes) of the source area, will be the counter for the 
//loop, hence we're going to scan 'byte-wise'
      L #tExtResets.repetition;
lp01:      T #loop01;


//open the first byte, and check it 'not equal zero'
      A(;
      L B[ AR1, P#0.0];
      L #hex00;
      <>I;
      );
//if its something else than zero (no jump), set '#qResExt' to '1' and exit loop
//if its zero (jump), put an offset to the AR1 (next byte) and go to next loop scan
      JCN next;
      S #qResExt;
      JU olop;


next:      +AR1 P#1.0;
      L #loop01;
      LOOP lp01;


olop:      NOP 0;


//if there is a external global request, set as well the output to true
      A #iResExt;
      S #qResExt;


END_FUNCTION
Code:
FUNCTION "2_SplitHMIReset" : VoidTITLE = Einzelquittierung von der Visualisierung splitten und in ein Strukt kopieren
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
   VAR_INPUT 
      iHmiResetArray : Any;   // Pointer of the source of all HMI reset requests (array of word)
      qHmiResetSplitted : Any;   // Pointer for the destination, where the requests will stored
      iHelpArray : Any;   // Pointer of the source with help flags (array of word)
      iEdgeEval : Bool;   // 1=with edge evaluation, 0=without edge evaluation
   END_VAR


   VAR_OUTPUT 
      qHmiReset : Bool;   // collective reset request from HMI received
   END_VAR


   VAR_TEMP 
      tiHmiResetArray : Struct   // splitted any pointer
         "10h" : Byte;
         DataType : Byte;
         repetition : Int;
         db_no : Int;
         adres : DWord;
      END_STRUCT;
      tqHmiResetSplitted : Struct   // splitted any pointer
         "10h" : Byte;
         DataType : Byte;
         repetition : Int;
         db_no : Int;
         adres : DWord;
      END_STRUCT;
      tiHelpArray : Struct   // splitted any pointer
         "10h" : Byte;
         DataType : Byte;
         repetition : Int;
         db_no : Int;
         adres : DWord;
      END_STRUCT;
      tEdgeEval : Bool;   // 1=with edge evaluation, 0=without edge evaluation
      loop01 : Int;   // loop counter
      retval : Int;   // just return value, for some 'calls'
      repetition_in_word : Int;   // interim value, for the calculation of the loop counter
      result_word_loop : Word;   // interim value, for saving
   END_VAR




BEGIN
NETWORK
TITLE = Initialisation
      A #iEdgeEval;
      = #tEdgeEval;
NETWORK
TITLE = Eingänge 'zerlegen' und in Lokaldaten kopieren
//###Split SourceAny into local data
//copy any pointer of source into AR1
      L P##iHmiResetArray;
      LAR1;
//copy any pointer of target into AR2
      LAR2 P##tiHmiResetArray;
//1st bytes is always 10h for s7
      L B[ AR1, P#0.0];
      T B[ AR2, P#0.0];
//copy data type
      L B[ AR1, P#1.0];
      T B[ AR2, P#1.0];
//copy repetition factor
      L W[ AR1, P#2.0];
      T W[ AR2, P#2.0];
//copy db number
      L W[ AR1, P#4.0];
      T W[ AR2, P#4.0];
//copy pointer (start adres)
      L D[ AR1, P#6.0];
      T D[ AR2, P#6.0];
//################################################


//###Split DestinationAny into local data
//copy any pointer of source into AR1
      L P##qHmiResetSplitted;
      LAR1;
//copy any pointer of target into AR2
      LAR2 P##tqHmiResetSplitted;
//1st bytes is always 10h for s7
      L B[ AR1, P#0.0];
      T B[ AR2, P#0.0];
//copy data type
      L B[ AR1, P#1.0];
      T B[ AR2, P#1.0];
//copy repetition factor
      L W[ AR1, P#2.0];
      T W[ AR2, P#2.0];
//copy db number
      L W[ AR1, P#4.0];
      T W[ AR2, P#4.0];
//copy pointer (start adres)
      L D[ AR1, P#6.0];
      T D[ AR2, P#6.0];
//################################################


//###Split DestinationAny into local data
//copy any pointer of source into AR1
      L P##iHelpArray;
      LAR1;
//copy any pointer of target into AR2
      LAR2 P##tiHelpArray;
//1st bytes is always 10h for s7
      L B[ AR1, P#0.0];
      T B[ AR2, P#0.0];
//copy data type
      L B[ AR1, P#1.0];
      T B[ AR2, P#1.0];
//copy repetition factor
      L W[ AR1, P#2.0];
      T W[ AR2, P#2.0];
//copy db number
      L W[ AR1, P#4.0];
      T W[ AR2, P#4.0];
//copy pointer (start adres)
      L D[ AR1, P#6.0];
      T D[ AR2, P#6.0];
//################################################
NETWORK
TITLE = Werte Einzelquittierung aus
//issue: the hmi is sending always '1' as acknowledgment for the corresponding
//fault, if there is no reset request neccessary.
//it's is not good style, to occupy the reset input of flip flop with a
//'1', if there is no reason for that.
//that is the reason, why we have to evaluate the rising edge (one shot) only.
//for that, unfortunately we need for each ack-bit a help bit.
//we are going to start a loop, whom the result will be stored in the local data
//after loop, the local data will be copied into the destination.


//open the source data block, where the acknowledgement bits are coming from
      OPN DB[ #tiHmiResetArray.db_no];
//load the start adres into AR1
      LAR1 #tiHmiResetArray.adres;


      L #tqHmiResetSplitted.repetition;
//divide by /2, hence we are going to scan wordwise
      L 2;
      /I;
      T #repetition_in_word;
lp01:      T #loop01;


//if EdgeEvaluation is not desired, jump directly to copying of data
//without evaluating of risingedge evaluation
      AN #tEdgeEval;
      JC noed;


//calculate coresponding adres for help words and open data instance
      L #tiHelpArray.adres;
//disable memory area format (usually b#16#84 (=DB) is located here
      AD DW#16#00ffffff;
//add '85' as memory area (=DI)
      OD dw#16#85000000;
//put the result into AR2
      LAR2;
//calculate offset for the adres
//1st run: e.g. (32-32)*2 = Offset = 0 bytes
//2nd run:  (32-31)*2 = 1*2= 2 bytes
//3rd run: (32-30)*2 = 6 bytes
//etc...
      L #repetition_in_word;
      L #loop01;
      -I;
      L 2                  ;//*2, hence we are scanning word-wise
      *I;
//bring to correct pointer format in bits = multiply by 8
      SLD 3;
//add the adres to AR2
      +AR2;
//opn data block in to DI register
      OPN DI[ #tiHelpArray.db_no];


//#############################################
//check for rising edge - wordwise
//check current values with help flags, if there is a difference
      L DBW[ AR1, P#0.0];
      L DIW[ AR2, P#0.0];
      INVI;
      AW;
//hence we have only two adres registers, we must save the value into
//local data, so that we can use it later
      T #result_word_loop;


//overwrite help flags with current values
      L DBW[ AR1, P#0.0];
      T DIW[ AR2, P#0.0];
      JU write;
//#############################################


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//this part will only be executed, if edge evaluation doesnt
//has been desired / not wished
noed:      L DBW[ AR1, P#0.0];
      T #result_word_loop;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


write:      NOP 0;
//calculate adres of target
//description, what we are doing here, is described few lines above
      L #tqHmiResetSplitted.adres;
      AD DW#16#00ffffff;
      OD dw#16#85000000;
      LAR2;
      L #repetition_in_word;
      L #loop01;
      -I;
      L 2                  ;//*2, hence we are scanning word-wise
      *I;
      SLD 3;
      +AR2;
      OPN DI[ #tqHmiResetSplitted.db_no];


//take the saved value from the local stack and put into the target
      L #result_word_loop;
      T DIW[ AR2, P#0.0];


//add offset of two for next scan into AR1
      +AR1 P#2.0;
      L #loop01;
      LOOP lp01;
NETWORK
TITLE = Globales Reset durch HMI - wurde irgendeine Einzelquittierung ausgeführt?
//initialise the local bool, for evaluating if any external reset is existent
      CLR;
      = #qHmiReset;


//here we are going to check, if there is any reset request existent from 
//the HMI... this will be done by a loop
//we are going to 'scan' bytewise


//as first, open the corresponding data block, where the information is stored
      OPN DB[ #tqHmiResetSplitted.db_no];


//load the adres pointer into AR1
      LAR1 #tqHmiResetSplitted.adres;
//the length (in bytes) of the source area, will be the counter for the 
//loop, hence we're going to scan 'byte-wise'
      L #tqHmiResetSplitted.repetition;
lp02:      T #loop01;


//open the first byte, and check it 'not equal zero'
      A(;
      L DBB[ AR1, P#0.0];
      L b#16#0;
      <>I;
      );
//if its something else than zero (no jump), set '#qResExt' to '1' and exit loop
//if its zero (jump), put an offset to the AR1 (next byte) and go to next loop scan
      JCN next;
      S #qHmiReset;
      JU olop;


next:      +AR1 P#1.0;
      L #loop01;
      LOOP lp02;


olop:      NOP 0;
END_FUNCTION
Code:
FUNCTION "3_CollectiveFault" : VoidTITLE = Prüfen auf Sammelfehler
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
//Dieses Baustein kann sechs Strukturen auf Sammelfehler überprüfen.
//Die Fehlerstrukturen müssen sich in einem globalen Datenbaustein (DB) befinden.
//Es dürfen nicht die Instanzdaten eines FB's ein (DI).
   VAR_INPUT 
      iGroup_All : Any;   // Pointer of the source, where all faults are located
      iGroup1 : Any;   // Pointer of a source/group, where should be shown for a collective fault
      iGroup2 : Any;   // Pointer of a source/group, where should be shown for a collective fault
      iGroup3 : Any;   // Pointer of a source/group, where should be shown for a collective fault
      iGroup4 : Any;   // Pointer of a source/group, where should be shown for a collective fault
      iGroup5 : Any;   // Pointer of a source/group, where should be shown for a collective fault
   END_VAR


   VAR_OUTPUT 
      qerror : Bool;   // Input parameters are wrong
      qFault_All : Bool;   // Collective Fault
      qFault1 : Bool;   // Collective fault in Group 01
      qFault2 : Bool;   // Collective fault in Group 02
      qFault3 : Bool;   // Collective fault in Group 03
      qFault4 : Bool;   // Collective fault in Group 04
      qFault5 : Bool;   // Collective fault in Group 05
   END_VAR


   VAR_TEMP 
      tGroupAll : Struct   // splitted any pointer
         "10h" : Byte;
         DataType : Byte;
         repetition : Int;
         db_no : Int;
         adres : DWord;
      END_STRUCT;
      tGroup1 : Struct   // splitted any pointer
         "10h" : Byte;
         DataType : Byte;
         repetition : Int;
         db_no : Int;
         adres : DWord;
      END_STRUCT;
      tGroup2 : Struct   // splitted any pointer
         "10h" : Byte;
         DataType : Byte;
         repetition : Int;
         db_no : Int;
         adres : DWord;
      END_STRUCT;
      tGroup3 : Struct   // splitted any pointer
         "10h" : Byte;
         DataType : Byte;
         repetition : Int;
         db_no : Int;
         adres : DWord;
      END_STRUCT;
      tGroup4 : Struct   // splitted any pointer
         "10h" : Byte;
         DataType : Byte;
         repetition : Int;
         db_no : Int;
         adres : DWord;
      END_STRUCT;
      tGroup5 : Struct   // splitted any pointer
         "10h" : Byte;
         DataType : Byte;
         repetition : Int;
         db_no : Int;
         adres : DWord;
      END_STRUCT;
      tloop : Int;
   END_VAR




BEGIN
NETWORK
TITLE = Initialisierung
      CLR;
      = #qerror;
      = #qFault_All;
      = #qFault1;
      = #qFault2;
      = #qFault3;
      = #qFault4;
      = #qFault5;
NETWORK
TITLE = Eingänge 'zerlegen' und in Lokaldaten kopieren
//###Split SourceAny into local data
//copy any pointer of source into AR1
      L P##iGroup_All;
      LAR1;
//copy any pointer of target into AR2
      LAR2 P##tGroupAll;
//1st bytes is always 10h for s7
      L B[ AR1, P#0.0];
      T B[ AR2, P#0.0];
//copy data type
      L B[ AR1, P#1.0];
      T B[ AR2, P#1.0];
//copy repetition factor
      L W[ AR1, P#2.0];
      T W[ AR2, P#2.0];
//copy db number
      L W[ AR1, P#4.0];
      T W[ AR2, P#4.0];
//copy pointer (start adres)
      L D[ AR1, P#6.0];
      T D[ AR2, P#6.0];
//################################################


//###Split SourceAny into local data
//copy any pointer of source into AR1
      L P##iGroup1;
      LAR1;
//copy any pointer of target into AR2
      LAR2 P##tGroup1;
//1st bytes is always 10h for s7
      L B[ AR1, P#0.0];
      T B[ AR2, P#0.0];
//copy data type
      L B[ AR1, P#1.0];
      T B[ AR2, P#1.0];
//copy repetition factor
      L W[ AR1, P#2.0];
      T W[ AR2, P#2.0];
//copy db number
      L W[ AR1, P#4.0];
      T W[ AR2, P#4.0];
//copy pointer (start adres)
      L D[ AR1, P#6.0];
      T D[ AR2, P#6.0];
//################################################


//###Split SourceAny into local data
//copy any pointer of source into AR1
      L P##iGroup2;
      LAR1;
//copy any pointer of target into AR2
      LAR2 P##tGroup2;
//1st bytes is always 10h for s7
      L B[ AR1, P#0.0];
      T B[ AR2, P#0.0];
//copy data type
      L B[ AR1, P#1.0];
      T B[ AR2, P#1.0];
//copy repetition factor
      L W[ AR1, P#2.0];
      T W[ AR2, P#2.0];
//copy db number
      L W[ AR1, P#4.0];
      T W[ AR2, P#4.0];
//copy pointer (start adres)
      L D[ AR1, P#6.0];
      T D[ AR2, P#6.0];
//################################################


//###Split SourceAny into local data
//copy any pointer of source into AR1
      L P##iGroup3;
      LAR1;
//copy any pointer of target into AR2
      LAR2 P##tGroup3;
//1st bytes is always 10h for s7
      L B[ AR1, P#0.0];
      T B[ AR2, P#0.0];
//copy data type
      L B[ AR1, P#1.0];
      T B[ AR2, P#1.0];
//copy repetition factor
      L W[ AR1, P#2.0];
      T W[ AR2, P#2.0];
//copy db number
      L W[ AR1, P#4.0];
      T W[ AR2, P#4.0];
//copy pointer (start adres)
      L D[ AR1, P#6.0];
      T D[ AR2, P#6.0];
//################################################


//###Split SourceAny into local data
//copy any pointer of source into AR1
      L P##iGroup4;
      LAR1;
//copy any pointer of target into AR2
      LAR2 P##tGroup4;
//1st bytes is always 10h for s7
      L B[ AR1, P#0.0];
      T B[ AR2, P#0.0];
//copy data type
      L B[ AR1, P#1.0];
      T B[ AR2, P#1.0];
//copy repetition factor
      L W[ AR1, P#2.0];
      T W[ AR2, P#2.0];
//copy db number
      L W[ AR1, P#4.0];
      T W[ AR2, P#4.0];
//copy pointer (start adres)
      L D[ AR1, P#6.0];
      T D[ AR2, P#6.0];
//################################################


//###Split SourceAny into local data
//copy any pointer of source into AR1
      L P##iGroup5;
      LAR1;
//copy any pointer of target into AR2
      LAR2 P##tGroup5;
//1st bytes is always 10h for s7
      L B[ AR1, P#0.0];
      T B[ AR2, P#0.0];
//copy data type
      L B[ AR1, P#1.0];
      T B[ AR2, P#1.0];
//copy repetition factor
      L W[ AR1, P#2.0];
      T W[ AR2, P#2.0];
//copy db number
      L W[ AR1, P#4.0];
      T W[ AR2, P#4.0];
//copy pointer (start adres)
      L D[ AR1, P#6.0];
      T D[ AR2, P#6.0];
//################################################
NETWORK
TITLE = Prüfe GroupAll nach einem Sammelfehler
//at first, we will check if the input any pointer contents meaningful
//data (db no, start adres, repetition factor)
//the pointer must contain a data block number
      O(;
      L #tGroupAll.db_no;
      L 0;
      <=I;
      );


//the pointer must containt a length/repetition factor
      O(;
      L #tGroupAll.repetition;
      L 0;
      <=I;
      );
//if one this checks are positive jump and dont execute the rest of 
//this network
      JC en01;


//check for the correct memory area '84' = data block
      O(;
      L #tGroupAll.adres;
//for comparing only the first byte with memory area, we must 'disable'
//the start adress (the following three bytes)
      AD dw#16#ff000000;
      L dw#16#84000000;
      <>I;
      );
//if one this checks are positive jump and dont execute the rest of 
//this network
      JC err1;


//########################################################################
//the structure will be scanned by a loop word-wise.
//if there is something equal than 'not zero' the corresponding
//flag will be set


//opn data block
      OPN DB[ #tGroupAll.db_no];
      LAR1 #tGroupAll.adres;
//&&&&&&&&&&&&&&& LOOP &&&&&&&&&&&&&&&&&&&&&&&&&
      L #tGroupAll.repetition;
//divide thorugh to, hence we are going to scan wordwise
      L 2;
      /I;
lp01:      T #tloop;


//if its not zero, set fault and jump out of the loop
      L W[ AR1, P#0.0];
      L 0;
      <>I;
      JCN ne01;
      S #qFault_All;
      JU en01;


ne01:      +AR1 P#2.0;
      L #tloop;
      LOOP lp01;
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      JU en01;


err1:      SET;
      S #qerror;


en01:      NOP 0;
NETWORK
TITLE = Prüfe Group1 nach einem Sammelfehler
//at first, we will check if the input any pointer contents meaningful
//data (db no, start adres, repetition factor)
//the pointer must contain a data block number
      O(;
      L #tGroup1.db_no;
      L 0;
      <=I;
      );


//the pointer must containt a length/repetition factor
      O(;
      L #tGroup1.repetition;
      L 0;
      <=I;
      );
//if one this checks are positive jump and dont execute the rest of 
//this network
      JC en02;


//check for the correct memory area '84' = data block
      O(;
      L #tGroup1.adres;
//for comparing only the first byte with memory area, we must 'disable'
//the start adress (the following three bytes)
      AD dw#16#ff000000;
      L dw#16#84000000;
      <>I;
      );
//if one this checks are positive jump and dont execute the rest of 
//this network
      JC err2;


//########################################################################
//the structure will be scanned by a loop word-wise.
//if there is something equal than 'not zero' the corresponding
//flag will be set


//opn data block
      OPN DB[ #tGroup1.db_no];
      LAR1 #tGroup1.adres;
//&&&&&&&&&&&&&&& LOOP &&&&&&&&&&&&&&&&&&&&&&&&&
      L #tGroup1.repetition;
//divide thorugh to, hence we are going to scan wordwise
      L 2;
      /I;
lp02:      T #tloop;


//if its not zero, set fault and jump out of the loop
      L W[ AR1, P#0.0];
      L 0;
      <>I;
      JCN ne02;
      S #qFault1;
      JU en02;


ne02:      +AR1 P#2.0;
      L #tloop;
      LOOP lp02;
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      JU en02;


err2:      SET;
      S #qerror;


en02:      NOP 0;
NETWORK
TITLE = Prüfe Group2 nach einem Sammelfehler
//at first, we will check if the input any pointer contents meaningful
//data (db no, start adres, repetition factor)
//the pointer must contain a data block number
      O(;
      L #tGroup2.db_no;
      L 0;
      <=I;
      );


//the pointer must containt a length/repetition factor
      O(;
      L #tGroup2.repetition;
      L 0;
      <=I;
      );
//if one this checks are positive jump and dont execute the rest of 
//this network
      JC en03;


//check for the correct memory area '84' = data block
      O(;
      L #tGroup2.adres;
//for comparing only the first byte with memory area, we must 'disable'
//the start adress (the following three bytes)
      AD dw#16#ff000000;
      L dw#16#84000000;
      <>I;
      );
//if one this checks are positive jump and dont execute the rest of 
//this network
      JC err3;


//########################################################################
//the structure will be scanned by a loop word-wise.
//if there is something equal than 'not zero' the corresponding
//flag will be set


//opn data block
      OPN DB[ #tGroup2.db_no];
      LAR1 #tGroup2.adres;
//&&&&&&&&&&&&&&& LOOP &&&&&&&&&&&&&&&&&&&&&&&&&
      L #tGroup2.repetition;
//divide thorugh to, hence we are going to scan wordwise
      L 2;
      /I;
lp03:      T #tloop;


//if its not zero, set fault and jump out of the loop
      L W[ AR1, P#0.0];
      L 0;
      <>I;
      JCN ne03;
      S #qFault2;
      JU en03;


ne03:      +AR1 P#2.0;
      L #tloop;
      LOOP lp03;
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      JU en03;


err3:      SET;
      S #qerror;


en03:      NOP 0;
NETWORK
TITLE = Prüfe Group3 nach einem Sammelfehler
//at first, we will check if the input any pointer contents meaningful
//data (db no, start adres, repetition factor)
//the pointer must contain a data block number
      O(;
      L #tGroup3.db_no;
      L 0;
      <=I;
      );


//the pointer must containt a length/repetition factor
      O(;
      L #tGroup3.repetition;
      L 0;
      <=I;
      );
//if one this checks are positive jump and dont execute the rest of 
//this network
      JC en04;


//check for the correct memory area '84' = data block
      O(;
      L #tGroup3.adres;
//for comparing only the first byte with memory area, we must 'disable'
//the start adress (the following three bytes)
      AD dw#16#ff000000;
      L dw#16#84000000;
      <>I;
      );
//if one this checks are positive jump and dont execute the rest of 
//this network
      JC err4;


//########################################################################
//the structure will be scanned by a loop word-wise.
//if there is something equal than 'not zero' the corresponding
//flag will be set


//opn data block
      OPN DB[ #tGroup3.db_no];
      LAR1 #tGroup3.adres;
//&&&&&&&&&&&&&&& LOOP &&&&&&&&&&&&&&&&&&&&&&&&&
      L #tGroup3.repetition;
//divide thorugh to, hence we are going to scan wordwise
      L 2;
      /I;
lp04:      T #tloop;


//if its not zero, set fault and jump out of the loop
      L W[ AR1, P#0.0];
      L 0;
      <>I;
      JCN ne04;
      S #qFault2;
      JU en04;


ne04:      +AR1 P#2.0;
      L #tloop;
      LOOP lp04;
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      JU en04;


err4:      SET;
      S #qerror;


en04:      NOP 0;
NETWORK
TITLE = Prüfe Group4 nach einem Sammelfehler
//at first, we will check if the input any pointer contents meaningful
//data (db no, start adres, repetition factor)
//the pointer must contain a data block number
      O(;
      L #tGroup4.db_no;
      L 0;
      <=I;
      );


//the pointer must containt a length/repetition factor
      O(;
      L #tGroup4.repetition;
      L 0;
      <=I;
      );
//if one this checks are positive jump and dont execute the rest of 
//this network
      JC en05;


//check for the correct memory area '84' = data block
      O(;
      L #tGroup4.adres;
//for comparing only the first byte with memory area, we must 'disable'
//the start adress (the following three bytes)
      AD dw#16#ff000000;
      L dw#16#84000000;
      <>I;
      );
//if one this checks are positive jump and dont execute the rest of 
//this network
      JC err5;


//########################################################################
//the structure will be scanned by a loop word-wise.
//if there is something equal than 'not zero' the corresponding
//flag will be set


//opn data block
      OPN DB[ #tGroup4.db_no];
      LAR1 #tGroup4.adres;
//&&&&&&&&&&&&&&& LOOP &&&&&&&&&&&&&&&&&&&&&&&&&
      L #tGroup4.repetition;
//divide thorugh to, hence we are going to scan wordwise
      L 2;
      /I;
lp05:      T #tloop;


//if its not zero, set fault and jump out of the loop
      L W[ AR1, P#0.0];
      L 0;
      <>I;
      JCN ne05;
      S #qFault2;
      JU en05;


ne05:      +AR1 P#2.0;
      L #tloop;
      LOOP lp05;
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      JU en05;


err5:      SET;
      S #qerror;


en05:      NOP 0;
NETWORK
TITLE = Prüfe Group5 nach einem Sammelfehler
//at first, we will check if the input any pointer contents meaningful
//data (db no, start adres, repetition factor)
//the pointer must contain a data block number
      O(;
      L #tGroup5.db_no;
      L 0;
      <=I;
      );


//the pointer must containt a length/repetition factor
      O(;
      L #tGroup5.repetition;
      L 0;
      <=I;
      );
//if one this checks are positive jump and dont execute the rest of 
//this network
      JC en06;


//check for the correct memory area '84' = data block
      O(;
      L #tGroup5.adres;
//for comparing only the first byte with memory area, we must 'disable'
//the start adress (the following three bytes)
      AD dw#16#ff000000;
      L dw#16#84000000;
      <>I;
      );
//if one this checks are positive jump and dont execute the rest of 
//this network
      JC err6;


//########################################################################
//the structure will be scanned by a loop word-wise.
//if there is something equal than 'not zero' the corresponding
//flag will be set


//opn data block
      OPN DB[ #tGroup5.db_no];
      LAR1 #tGroup5.adres;
//&&&&&&&&&&&&&&& LOOP &&&&&&&&&&&&&&&&&&&&&&&&&
      L #tGroup5.repetition;
//divide thorugh to, hence we are going to scan wordwise
      L 2;
      /I;
lp06:      T #tloop;


//if its not zero, set fault and jump out of the loop
      L W[ AR1, P#0.0];
      L 0;
      <>I;
      JCN ne06;
      S #qFault2;
      JU en06;


ne06:      +AR1 P#2.0;
      L #tloop;
      LOOP lp06;
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      JU en06;


err6:      SET;
      S #qerror;


en06:      NOP 0;
END_FUNCTION
 
Zuletzt bearbeitet:
Zurück
Oben