Creazione di una funzione che copia elemento per elemento il contenuto di un array (nell’esempio sotto “array1”) in un altro array (“array2”).
La funzione che vado a creare avrà due variabili di tipo Pointer (“array1_ptr” che è la variabile in ingresso, e “array2_ptr” che è dichiarata come variabile di output) e una variabile intera (variabile “dim” dichiarata come input) che rappresenta la dimensione minima tra i due array. Ovviamente le due variabili Pointer puntano all’indirizzo di memoria del primo elemento dei rispettivi array (vedi questi articoli “Utilizzo di variabili Pointer”,“Array dinamico incrementale”).
Lo scopo di questa funzione è quello di copiare elemento per elemento il contenuto dell’array1 (ossia l’array a cui punta il puntatore “array1_ptr”) sull’array2 (ossia l’array a cui punta il puntatore “array2_ptr”).
La funzione spiegata passaggio per passaggio è la seguente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | FUNCTION "copia_array1_in_array_2_dinamico_pointer_1" : Void { S7_Optimized_Access := 'FALSE' } VERSION : 0.1 VAR_INPUT array1_ptr : Pointer; dim : Int; END_VAR VAR_OUTPUT array2_ptr : Pointer; END_VAR VAR_TEMP numb_db_array1 : Word; numb_db_array2 : Word; save_ar2 : DWord; count1 : Int; END_VAR BEGIN NETWORK TITLE = //funzione che copia il contenuto di array1 in array2, dim è la dimensione dell'array più piccolo L P##array1_ptr; //carica il Pointer array1_ptr in ACCU1 LAR1; //carica il contenuto di ACCU1 su AR1 L W[ AR1, P#0.0] ;// Carico su ACCU1 i primi due Byte del Pointer array1_ptr che rappresentano il numero del blocco dati (DB_number) T #numb_db_array1;//trasferisco ACCU1 su numb_db_array1 per riutilizzarlo dopo quando devo aprire il blocco dati L D[ AR1, P#2.0];// carico su ACCU1 i byte 2,3,4,5 (ossia 32bit) che corrispondono all'area di memoria a cui punta il puntatore array1_ptr all'intero del DB LAR1;// carico l'indizizzo precedente su AR1 //salvo ar2 su doubleword e lo ripristino a fine funzione (questo perchè AR2 è utilizzato dal processore e non ripristinarlo può causare problemi) TAR2; T #save_ar2; L P##array2_ptr; LAR2;// carico l'indizizzo del puntatore su AR2 L W[ AR2, P#0.0];// Carico su ACCU1 i primi due Byte del Pointer array2_ptr che rappresentano il numero del blocco dati (DB_number) T #numb_db_array2;//trasferisco ACCU1 su numb_db_array2 per riutilizzarlo dopo quando devo aprire il blocco dati L D[ AR2, P#2.0];// carico su ACCU1 i byte 2,3,4,5 (ossia 32bit) che corrispondono all'area di memoria a cui punta il puntatore array2_ptr all'intero del DB LAR2;// carico l'indizizzo precedente su AR2 L #dim;//carico su ACCU1 la più piccola dimensione tra i due array (dim è un input della funzione) inizio: T #count1 ;// inizio un loop OPN DB[ #numb_db_array1];//apro il blocco dati DB dove è presente l'array a cui punta il puntatore array1_ptr L W[ AR1, P#0.0];//carico su ACCU1 l'elemento array1[dim-count1] (dove l'array1 è un array di interi o Word a cui punta array1_ptr) OPN DB[ #numb_db_array2];//apro il blocco dati DB dove è presente l'array a cui punta il puntatore array2_ptr T W[ AR2, P#0.0];// trasferisco il valore presente in ACCU1 su array2[dim-count1], cioè array2[dim-count1]=array1[dim-count1] +AR1 P#2.0;// "incremento" AR1 di 2 byte, ossia nel ciclo successivo del loop l'indirizzo in AR1 è quello della word immediatamente succesiva (elemento successivo) +AR2 P#2.0;//come sopra ma per AR2 L #count1; LOOP inizio;//ripeto il loop fino a quando ACCU1, ossia count1>0 (ad ogni ciclo di loop count1 viene decrementato di 1) L #save_ar2; LAR2;//ripristino AR2 precedentemente salvato END_FUNCTION |
Si potrebbe anche evitare di usare AR2 utilizzando due variabili temporanee che salvano rispettivamente l’indirizzo dell’array1 e dell’array2 all’interno dei rispettivi DB. Definendo quindi le variabili “#indirizzo_array1” e “#indirizzo_array2”, posso modificare la funzione sopra e ho quindi:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | FUNCTION "Prova" : Void { S7_Optimized_Access := 'FALSE' } VERSION : 0.1 VAR_INPUT array1_ptr : Pointer; dim : Int; END_VAR VAR_OUTPUT array2_ptr : Pointer; END_VAR VAR_TEMP num_db1 : Word; num_db2 : Word; indirizzo_array1 : DWord; indirizzo_array2 : DWord; count1 : Int; int_tmp1 : Int; int_tmp2 : Int; END_VAR BEGIN NETWORK TITLE = L P##array1_ptr; LAR1; L W[ AR1, P#0.0]; T #num_db1; L D[ AR1, P#2.0]; T #indirizzo_array1; L P##array2_ptr; LAR1; L W[ AR1, P#0.0]; T #num_db2; L D[ AR1, P#2.0]; T #indirizzo_array2; L #dim; inizio: T #count1; L #indirizzo_array1; LAR1; OPN DB[ #num_db1]; L W[ AR1, P#0.0]; T #int_tmp1; +AR1 P#2.0; TAR1; T #indirizzo_array1; L #indirizzo_array2; LAR1; L #int_tmp1; OPN DB[ #num_db2]; T W[ AR1, P#0.0]; +AR1 P#2.0; TAR1; T #indirizzo_array2; L #count1; LOOP inizio; END_FUNCTION |