Vai al contenuto
PLC Forum


Indirizzamento assoluto dati in ingresso FC


acquaman

Messaggi consigliati

Ciao a tutti e buon natale,

Sto creando un FC con come parametro in ingresso una variabile DATE_AND_TIME quindi 8 Byte.

Da questa variabile devo estrapolare Anno, Mese, e giorno quindi copiare i Byte 1,2,3 e convertendoli da BCD in intero caricarli in 3 word.

 

Che sigla hanno i dati in ingresso di un FC, se fossero dati temporanei sarebbe:
L LB0

Fosse un FB sarebbe:

L DIB0

ma i dati in ingresso di un FC si possono richiamare senza il simbolico?

 

Ciao Grazie

Link al commento
Condividi su altri siti


puoi usare 2 metodi,

il primo usi il registro indirizzi AR1, ipotizziamo che il parametro date_and_time si chiami data, fai:

L p##data  carichi il puntatore al par di input

LAR1           lo scrivi nel registro AR1

poi con 

L b[ar1,p#0.0]  leggi il byte 0

L b[ar1,p#1.0]  leggi il byte 1 e così via,

non sono sicuro del primo metodo, il secondo funziona sicuramente, usi la sfc blockmove, dichiari una temporanea di tipo date_and_time, con la sfc copi il par di input nella temporanea e poi usi il solito metodo L LB0, L LB1 ecc

 

Link al commento
Condividi su altri siti

Non sono riuscito a far funzionare nessuno dei e metodi,

Il primo cpu in errore.

Il secondo l'SFC non accetta la variabile in ingresso, la riga resta rossa.

Link al commento
Condividi su altri siti

Acquaman, sinceramente non ho mai lavorato con dt# in input e non ho la minima idea di come funzioni. (appena provato anche io, in effetti il parametro che gli passi in formato dt non se lo calcola proprio..)

Però puoi farti furbo..

Tempo fa ti risposi così >> Topic

In sostanza, cambia la tua variabile in input da datetime in pointer.

Io la prova l'ho fatta con una db per comodità.

db2.db 0, formato date and time

fc2 è quello che richiamo da fc1, ed è impostato così:

L     P##POINTER // Variabile in ingresso di tipo pointer
      LAR1  
      L     W [AR1,P#0.0]
      T     #numdb // Memorizzo la numero della db che mi arriva da pointer
      AUF   DB [#numdb] // Richiamo la db
      L     DBB    0 // Qui avrò l'anno
      BTI   
      +     2000
      T     #ANNO // Out in formato int
      L     DBB    1 // Qui avrò il mese
      BTI   
      T     #MESE // Out in formato byte
      L     DBB    2 // Qui avrò il giorno
      BTI   
      T     #GIORNO // Out in formato byte
      L     DBB    3 // Qui avrò l'ora
      BTI   
      T     #ORA // Out in formato byte
      L     DBB    4 // Qui avrò i minuti
      BTI   
      T     #MINUTO // Out in formato byte

In pratica imposti la tua data su quella db e fc2 non elabora direttamente il dato ma andrà a puntare la lettura su quella db.

 

Spero di esser stato chiaro, immagini esplicative non me ne fa caricare

Link al commento
Condividi su altri siti

dovresti dichiarare la tua struttura dati , che contenga una data o no , come Any .

Poi all'interno del tuo blocco funzione devi fare qualcosa del genere , presupponi che il dato da passare come IN  sia Any e si chiami Message ....

 

TAR2  
      T     #ar2_memo

      L     P##MESSAGE
      LAR1  
      L     P##pMessage
      LAR2  
      L     W [AR1,P#0.0]
      T     LW [AR2,P#0.0]
      L     W [AR1,P#2.0]
      T     LW [AR2,P#2.0]
      L     W [AR1,P#4.0]
      T     LW [AR2,P#4.0]
      L     W [AR1,P#6.0]
      T     LW [AR2,P#6.0]
      L     W [AR1,P#8.0]
      T     LW [AR2,P#8.0]

      L     #ar2_memo
      LAR2  

 

all'interno del tuo blocco lavori con il puntatore  #pMessage che rappresenta la tua struttura dati locale che puoi manipolare come vuoi .

Come vedi sopra il codice non fa altro che copiare il contenuto di un puntatore in un altro puntatore

In questo modo automaticamente, all'esterno della funzione ti ritrovi i dati sulla tua struttura globale 

Link al commento
Condividi su altri siti

 

puoi richiamare la funzione nel OB1 oppure passare il dato tramite N funzioni che appoggiano il suo valore sulle temp di ogni rispettiva funzione ed annidarlo finchè il OS te lo concede.Le operazioni le fai all'interno della funzione dove fai la copia dei puntatori , usi le temp dell FCxx

Link al commento
Condividi su altri siti

Passare un parametro di input di tipo composto, come il DATE_AND_TIME, da una FC ad un'altra FC annidata, non è mai possibile, provare per credere.

Piuttosto il problema iniziale posto da Acquaman può essere risolto con il seguente codice posto all'interno della funzione, alla quale viene passato su DT1 in input direttamente la variabile  OB1_DATE_TIME :

      L     P##dt1     // ottiene il puntatore al puntatore che punta alla variabile in ingresso
      LAR1  
      L     W [AR1,P#0.0]
      L     D [AR1,P#2.0]
      LAR1  // punta utilizzando il puntatore di livello 2
      L     D [AR1,P#0.0]  // qui ci sono i primi 4 byte di OB1_DATE_TIME
      L     D [AR1,P#4.0] // qui i restanti 4

Ovviamente per rendere il codice universale, ossia per farlo funzionare anche se a DT1 si passa una DB, bisogna controllare il tipo puntato prima di accedervi, e prendere le contromisure giuste (ad esempio aprire prima la DB).

 

Link al commento
Condividi su altri siti

Ciao stilnovo, non ho mai provato a passare un DATE_AND_TIME prima d'ora, e devo dire che avrei provato anch'io a caricare il puntatore e puntare subito ai bytes, tu invece hai aggiunto queste operazioni:

      L     W [AR1,P#0.0]
      L     D [AR1,P#2.0]
      LAR1  // punta utilizzando il puntatore di livello 2
 

Confermo che senza di queste non funziona, puoi spiegarmi meglio il significato di questo che tu chiami puntatore di livello 2 ?

 

Link al commento
Condividi su altri siti

In pratica, quando si ha un parametro composto, la CPU è costretta a passare il suo puntatore, non potendo passare il valore visto che eccede i 32 bit. Quindi puntando il parametro non si accede direttamente al valore, ma all'ulteriore puntatore che punta effettivamente al valore desiderato. Quando invece dichiariamo il parametro di input come any, pointer oppure struct tipo semplice (es.INT), il primo puntatore non è gestito dalla CPU a RUNTIME, ma direttamente dal compilatore in fase di scrittura del codice. In esecuzione si interagisce pertanto sempre e solo con il "secondo" puntatore, ecco perché "di solito" funziona anche utilizzando solamente il primo LAR1, senza necessità di deferenziare ulteriormente. Non è proprio immediato, ma con CPU ONLINE alla mano ed un po' di prove risulta più comprensibile.

 

Link al commento
Condividi su altri siti

Grazie, ho capito, passa un puntatore e non un valore.

Nel codice che hai scritto secondo me l'istruzione  L  W [AR1,P#0.0]  non serve a niente, ho provato senza e funziona lo stesso.

Link al commento
Condividi su altri siti

Quote

Quella istruzione superflua, cosa dovrebbe contenere per caso il numero della DB?

Si, confermo essendo un POINTER nei primi 2 bytes c'è 0 oppure il numero della DB.

Ho scritto che era superflua perchè provando avevo passato come parametro #OB1_DATE_TIME.

Nel caso tu abbia il valore in DB ti serve anche quel dato per aprire la DB:

      L     W [AR1,P#0.0]
      T     #NrDB
      AUF   DB [#NrDB]
 

Provato con Plcsim e funziona alla grande, bravo stilnovo!

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