Vai al contenuto
PLC Forum


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


Messaggi consigliati

Inserito:

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.

 


Inserita:

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.

Inserita:

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.

Inserita: (modificato)

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
Inserita:

android633 ho scaricato il file. Con quale programma bisogna aprire un file con espansione .ap13?

Inserita: (modificato)

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

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