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 :icon_mrgreen:
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...
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 :icon_mrgreen:
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