Vai al contenuto
PLC Forum


AWL parametrizzato??????????


luca959697

Messaggi consigliati

Devo scrivere in un fc parametrizzato.

1) ES: Nel  DB1 (DB_A)

STRUCT

0.1 (OFSET)  COMANDO (NOME) BOOL (TIPO DI DATO)

Io vorrei scrivere:

A "DB_A". COMANDO

S BIT

Nel FC parametrizzato come variabile IN: DB_1 (NOME)  BLOCK_DB (TIPO DI DATO)

Poi scrivo

A #DB_1.DBX0.1  (mi dà errore)

Invece se scrivo

OPN #DB_1

A DBX0.1 (Ok)

Perché nel primo caso mi dà errore?

2)

ES: Nel DB6 (DB_A) ho questa situazione:

STRUCT

RIPRISTINO (NOME)   ARRAY [1..10]

Nel FC scrivo i parametri IN: DB_1 (NOME)  BLOCK_DB (TIPO DI DATO) INDICE INT (TIPO DI DATO)

Io vorrei scrivere: #DB_1.RIPRISTINO[INDICE]

come faccio a scriverlo usando AWL

3)

ES: NEL DB3 (DB_B) ho questa situazione:

STRUCT

B  (NOME)   "UDT_B" (TIPO DI DATI)                   (UDT_B è composto da 20 BOOL)

Nel FC scrivo i parametri IN/OUT: UDT_PROVA (NOME) "UDT_B" (TIPO DI DATI)

Voglio resettare tutti i BOOL di questo UDT e controllare che nessuno dei BOOL di questo UDT abbia assunto valore 1. Questo lo devo fare come negli altri esempi in AWL in un FC parametrizzato.

 

Link al commento
Condividi su altri siti


Ciao,

premetto che utilizzo poco AWL, ma prova a risponderti lo stesso.

1) Semplicemente perchè non si può: il prefisso # indica al compilatore che stai utilizzando un puntatore; i puntatori per AWL Siemens sono Int o DInt, se ricordo bene, mentre con DB_1.DBX0.1 tu stai utilizzando un bit; per definizione, un puntatore è l'indirizzo ad un area di memoria (quindi un numero).

2) In AWL Siemens non puoi utilizzare come indice di un array una variabile, ma sempre e solo una costante: non puoi scrivere ARRAY[INDICE], ma solo ARRAY[1] (secondo me, questo è uno dei punti deboli del linguaggio AWL); in sostanza, sei costretto a dimesionare ed utilizzare un puntatore.

3) Se la tua Struct è composta da 32 bit posti all'inizio del blocco dati, ad esempio, per azzerarli basta che fai un move 0 a DBn.DBD0, utilizzando l'indirizzamento assoluto; la stessa cosa puoi farla con un confronto, per sapere se uno dei bit è TRUE (con 20 bit credo cambi poco); in questo modo, però, DBnDBD0 non ha simbolo e non può averlo; un altro modo è quello di utilizzare i puntatori e ciclare verificando o azzerando tutti i bit contenuti nella Struct.

Ti consiglio di scaricarti e leggerti la guida di Federico Milan proprio sull'utilizzo dei puntatori ("Puntatori S7" e dovrebbe essere nela sezione download del forum) e di guardarti gli innumerevoli post sull'argomento, sempre sul forum; se cerchi Siemens SIOS con il tuo motore di ricerca preferito, lì troverai, invece, le guide ufficiali di Siemens sul linguaggio AWL: sui puntatori esiste una intera sezione.

Link al commento
Condividi su altri siti

1) Come detto da Drugo, semplicemente perché non si può. Non è però per il discorso "puntatore". Il puntatore viene definito con #P. Il solo carattere # indica che si accede ad una variabile dell'interfaccia delle variabili della funzione.

 

2) Non poter scrivere Array[indice] non è un limite del linguaggio AWL, ma del 300/400. Infatti non puoi usare quella sintassi nemmeno in KOP, ma solo in SCL.

Con il 1200 lo puoi fare in SCL e in KOP (l'AWL non c'è). Con il 1500 in SCL, in KOP e in AWL.

Link al commento
Condividi su altri siti

Ho fatto per esercitarmi delle funzioni che accedono ad uno specifico indice di un array in STL, nello specifico in questo file ( https://mega.nz/#!fkR2xATB!mR_9c9SksWYeUxcKcLkDFfgNFfU4QHDo0RdHxGkiCnE ) trovi le seguenti funzioni:

 

array_dinamico_incrementale (FC3): riceve in ingresso il primo elemento dell'array (tipo pointer) e la dimensione, poi riempe tutti i valori in maniera incrementale, ossia array[0]=0, array[1]=1, array[n]=n, array[dim]=dim-1.

 

copia_array1_in_array_2_dinamico_pointer (FC4): funzione che copia il contenuto di array1 in array2, dim è la dimensione dell'array più piccolo

 

somma_di due_array_elemento_per_elemento (FC5): esegue la somma di due array elemento per elemento, e copia il risultato in un terzo array
sia i due array in ingresso che quello in uscita sono di tipo pointer, la dimensione dim è pari a quella dell'array più piccolo.

 

ci sono poi queste altre due funzioni per resettare il tuo User_Data_type da 20 Bool

 

luca959697_resetta_UDT_con_pointer (FC1) :

      L P##UDT_ptr               //dove UDT_ptr è un Input di tipo Pointer
      LAR1
      L W [ AR1 , P#0.0 ]
      T     #numb_db
      L D [ AR1 , P#2.0 ]
      LAR1
      L     w#16#0
      OPN DB [ #numb_db]
      T W [ AR1 , P#0.0 ]        //resetta i primi 16 bit
      L B [ AR1 , P#2.0 ]        //carica gli 8 bit successivi ai primi 16
      L     b#16#f0              // carica in accu1 11110000
      AW                         //faccio l'and in modo da azzerare solo i primi 4 bit e lasciare intatti gli altri
      T B [ AR1 , P#2.0 ]

 

e l'altra funzione in alternativa a FC1 è luca959697_resetta_UDT_senza_pointer (FC6):

 

      R     #UDT_PROVA.Element_1    //dove UDT_PROVA è un InOut di Tipo UDT_B (User Date Type composto da 20 Bool)
      R     #UDT_PROVA.Element_2
      R     #UDT_PROVA.Element_3
      R     #UDT_PROVA.Element_4
      R     #UDT_PROVA.Element_5
      R     #UDT_PROVA.Element_6
      R     #UDT_PROVA.Element_7
      R     #UDT_PROVA.Element_8
      R     #UDT_PROVA.Element_9
      R     #UDT_PROVA.Element_10
      R     #UDT_PROVA.Element_11
      R     #UDT_PROVA.Element_12
      R     #UDT_PROVA.Element_13
      R     #UDT_PROVA.Element_14
      R     #UDT_PROVA.Element_15
      R     #UDT_PROVA.Element_16
      R     #UDT_PROVA.Element_17
      R     #UDT_PROVA.Element_18
      R     #UDT_PROVA.Element_19
      R     #UDT_PROVA.Element_20

Ovviamente sono bene accettate le critiche:thumb_yello:, visto che sto ancora imparando :smile:

 

 

 

Modificato: da android633
Link al commento
Condividi su altri siti

io uso TIA Portal v13, se non hai TIA portal ti posto qua le funzioni:

 

array_dinamico_incrementale (FC3):  riceve in ingresso il primo elemento dell'array (tipo pointer) e la dimensione, poi riempe tutti i valori in maniera incrementale, ossia array[0]=0, array[1]=1, array[n]=n, array[dim]=dim-1.

 

Variabili Input: Array_ptr (Pointer), dim (Int);

Variabili Temp: numb_db (Word), count1(Int)

 

      L  P##Array_ptr  //Array_ptr è un Input di tipo Pointer
      LAR1
      L W [ AR1 , P#0.0 ] // Carico su ACCU1 i primi due Byte del Pointer Array_ptr che rappresentano il numero del blocco dati (DB_number)
      T     #numb_db     //trasferisco ACCU1 su numb_db 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 Array_ptr all'intero del DB
      LAR1 // carico l'indizizzo precedente su AR1
      L     #dim //carico su ACCU1 la dimensione dell'array a cui punta il puntatore Array_ptr
inizio : T  #count1 // inizio un  loop
      L     #dim
      L     #count1
      -I                      // faccio la differenza tra dim e count1 per avere array[0]=0,  array[1]=1, altrimenti avrei array[0]=dim-1, array[1]=dim-2 ecc..
      OPN DB [ #numb_db] //apro il blocco dati DB dove è presente l'array a cui punta il puntatore Array_ptr
      T W [ AR1 , P#0.0 ] // trasferisco il valore contenuto in ACCU1 (che sarebbe dim-count1) all'indirizzo corrispondente ad array[dim-count1], quindi array[0]=0, array[1]=1, ..
      +AR1  P#2.0 // "incremento" AR1 di 2 byte, ossia nel ciclo successivo del loop, l'indirizzo in AR1 è quello dell'elemento immediatamente successivo dell'array
      L     #count1
      LOOP  inizio  //ripeto il loop fino a quando ACCU1, ossia count1>0 (ad ogni ciclo di loop count1 viene decrementato di 1)

 

_________________________________________________________________________________________________________________________________________

 

copia_array1_in_array_2_dinamico_pointer (FC4): funzione che copia il contenuto di array1 in array2, dim è la dimensione dell'array più piccolo

Variabili Input: array1_ptr (Pointer), dim (Int)

Variabili Temp: numb_db_array1 (Word), numb_db_array2 (Word), save_ar2 (DWord), count1 (Int)

Output: array2_ptr (Pointer)

      L  P##array1_ptr
      LAR1
      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

 

_________________________________________________________________________________________________________________________________________

 

somma_di due_array_elemento_per_elemento (FC5): esegue la somma di due array elemento per elemento, e copia il risultato in un terzo array
sia i due array in ingresso che quello in uscita sono di tipo pointer, la dimensione dim è pari a quella dell'array più piccolo.

Variabili Input: array1_ptr (Pointer), array2_ptr (Pointer), dim (Int)

Variabili Temp: numb_db_array1 (Word), numb_db_array2 (Word), numb_db_array_sum (Word), save_ar2 (DWord), count1 (Int), ar1_array1 (DWord), ar1_array2 (DWord), ar1_sum (DWord), tmp_sum (Int), tmp_int1 (Int), tmp_int2 (Int)

Variabili Output: array_sum_ptr (Pointer)

 

      L     P##array_sum_ptr
      LAR1
      L W [ AR1 , P#0.0 ] // Carico su ACCU1 i primi due Byte del Pointer array_sum_ptr che rappresentano il numero del blocco dati (DB_number)
      T     #numb_db_array_sum //trasferisco ACCU1 su numb_db_array_sum 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 array_sum_ptr all'intero del DB
      T     #ar1_sum //salvo l'indirizzo del primo elemento dell'array_sum (che è l'array di destinazione a cui punta il puntatore array_sum_ptr )

     

      L     P##array1_ptr
      LAR1
      L W [ AR1 , P#0.0 ]
      T     #numb_db_array1
      L D [ AR1 , P#2.0 ]
      T     #ar1_array1 //come sopra salvo l'indirizzo del primo elemento dell'array1 (che è l'array a cui punta array1_ptr)(è l'indirizzo all'interno del blocco dati numb_db_array1)

     

      L     P##array2_ptr
      LAR1
      L W [ AR1 , P#0.0 ]
      T     #numb_db_array2
      L D [ AR1 , P#2.0 ]
      T     #ar1_array2 //come sopra salvo l'indirizzo del primo elemento dell'array2 (che è l'array a cui punta array2_ptr)(è l'indirizzo all'interno del blocco dati numb_db_array2)

     

      L     #dim
inizio : T  #count1   //inizio il loop
      L     #ar1_array1
      LAR1 //carico su ar1 l'indirizzo dell'elemento dell'array1, ovvero array1[dim-count1] (questo indirizzo è l'indirizzo all'interno del blocco dati numb_db_array1)
      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)
      T     #tmp_int1 //trasferisco tale valore sulla variabile temporanea tmp_int1
      +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)
      TAR1 //trasferisco ar1 su ACCU1
      T     #ar1_array1 // salvo il nuovo indirizzo dell'elemento successivo dell'array

     

      L     #ar1_array2
      LAR1
      OPN DB [ #numb_db_array2]
      L W [ AR1 , P#0.0 ]
      T     #tmp_int2
      +AR1  P#2.0
      TAR1
      T     #ar1_array2  //tutto ugale a prima solo che viene fatto per l'array2.

     

      L     #tmp_int1
      L     #tmp_int2
      +I
      T     #tmp_sum // faccio la somma dei due valori, ossia array1[dim-count1]+array2[dim-count1] e la salvo su tmp_sum

     

      L     #ar1_sum
      LAR1
      L     #tmp_sum
      OPN DB [ #numb_db_array_sum]
      T W [ AR1 , P#0.0 ]
      +AR1  P#2.0
      TAR1
      T     #ar1_sum
      L     #count1
      LOOP  inizio

 

_______________________________________________________________________________________________________________

 

*NOTA: In tutti i casi l'array a cui punta il puntatore Array_ptr deve essere di interi o di word, ossia i sui elementi devono essere di 16bit.

 

Modificato: da android633
Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...