Vai al contenuto
PLC Forum


Puntatori in AWL capire funzionamento.


nietzsche1979

Messaggi consigliati

Ciao ragazzi, 

sono un programmatore di linguaggi ad alto livello (c#, vb net ecc), nel passato ho programmato anche in c++ e c con i puntatori, ma è un bel pezzo che non me ne occupo.

Devo fare manutenzione a del codice PLC (è qualche anno che faccio questa cosa, ma non ho mai scritto qualcosa di totalmente nuovo, faccio solo manutenzione).

Mi sono imbattuto in questa porzione di codice, la quale in soldoni crea un puntatore, per poter copiare una porzione di una DB indicizzata e con la funzione BLKMOV (quindi copia un'area di memoria in un altra).

 

Ma avrei varie domande, sia sulla sintassi che su come si comporta:

Prima di postare il codice provo a spiegare un po' di cose:

 

La db di origine è la DB103 nella quale sono memorizzate una struttura dati che rappresenta un carrello e che ha dimensione 50byte:

dalla 0 alle 49. Carrello 1

dalla 50 alla 99 Carrello 2

...

 

#DB_Carr   è valorizzato con 103 (il numero della DB, DB 103)

#OffSet_Record_Car      è calcolato nel con la formula (#carrello -1) * 50 byte, quindi il primo carrello è nell'area 0 - 49, il secondo 50 - 99, ecc come mi aspettavo.

#Len_Byte_Record_Car  è settato a 50 byte

 

Questo è il codice del programmatore creatore dell'applicativo con i suoi commenti

 

// 1)

      L     P##Punt_Record_Sts_Car      // Carica l'indirizzo del puntatore per l'area sorgente nel registro di indirizzo 1
      LAR1  
      L     W#16#1002                           // Scrive l'identificativo dell'area dati nel puntatore ANY per la sorgente
      T     LW [AR1,P#0.0]

 

// 2)

      L     #DB_Carr                              // Scrive puntatore DB nel puntatore ANY per la sorgente
      T     LW [AR1,P#4.0]

 

// 3)

      L     #OffSet_Record_Car            // Converte l'inizio dell'area dati sorgente in formato puntatore
      SLD   3
      OD    DW#16#84000000              // Collega l'identificativo dell'area
      T     LD [AR1,P#6.0]                      // Scrive nel puntatore ANY per la sorgente

 

4)

      L     #Len_Byte_Record_Car
      T     LW [AR1,P#2.0]
 

 

Poi fa una BLKMOV da Punt_Record_Sts_Car a una sua struttura dati.

 

 

Il mio problema è che non capisco bene la sintassi e cosa fa, ho cercato nei vari altri post, vi è codice simile, ma faccio confusione, quindi provo a chiedere.

Ho suddiviso il codice in quattro porzioni che credo siano quelle significative (credo)

 

La 1) Dichiara il puntatore e gli da un nome 1002 per poi memorizzarlo in AR1? 

         In varie parti del programma fa questa cosa, con  puntatori diversi  (Punt_Record_Sts_Car1, Punt_Record_Sts_Car2, ecc) ma caricando sempre  W#16#1002 e mettendola in LW                [AR1,P#0.0]

         Credo di aver capito che la costante può anche essere cambiata (1001, 1002, 1003, o altro, ditemi se sbaglio) ma che deve essere sempre memorizzata in [AR1,P#0.0]

 

2) Mi fa puntare alla DB103, la sorgente deve essere messa sempre in LW [AR1,P#4.0]?

 

3) MI fa puntare alla zona della memoria che davvero mi interessa (ovvero se fosse il carrello 2 al byte 50 della DB103, se fosse il carrello 3 al byte 100, eccetera).

    Va sempre messo in  LD [AR1,P#6.0] ???

  

    Poi capisco è lo shift a sinistra di 3 (quindi moltiplicare * 8) ma non l' OR bit a bit con quella costante.

 

    Cioè ponendo che io voglia il carrello 3: byte 100 ovvero dal bit 800.0 in su

    OffSet_Record_Car      =  (3 -1) * 50 = 100       (da quel che ho capito lo calcola così)

    100 * 8 (shift a sinistra) ottengo 800 (che dovrebbe andare bene)

 

    800 decimale, binario 1100100000

    in or con 

    84000000 binario 101000000011011110100000000

 

    avendo due dimensioni diverse credo che si debbano aggiungere degli zeri a sinistra e poi fare l' OR? o sbaglio? ma a cosa serve?

 

4) Mette la dimensione che si vuole puntare e che poi sarà copiata.

   Va sempre messa in LW [AR1,P#2.0]?

 

 

Quindi, oltre alle altre domande, chiedo anche

P#0.0 va il "nome"?

P#2.0 va la il numero di byte da puntare?

P#4.0 va l'indirizzo iniziale da puntare (DB103)

P#6.0 va l'offset?  800 bit della db 103  ma l'OR con 84000000 come modifica questo valore???

 

 

Grazie anticipatamente a che possa/voglia rispondermi, e comunque a chiunque spenda del tempo anche solo a leggere.

Ciao e a presto

 

 

 

 

 

 

 

 

 

 

 

Link al commento
Condividi su altri siti


Scusate se scrivo ancora, credo di aver intuito che OR con  84000000  serve per far puntare il puntatore (scusare l'espressione) o all'area dei Merker o a quella delle DB, giusto?

Quindi deduci che con l'OR punti alle DB e che senza (o con l'or per un altra costante che non conosco) lo faccia puntare ai merker.

Sbaglio?

Grazie ancora

Link al commento
Condividi su altri siti

Mi sembra che tu non abbia ben chiaro il formato del puntatore di tipo ANY.

Apri la guida tramite il Simatic Manager e nel campo di ricerca dell'indice scrivi "Formato puntatore"  poi selezioni "tipo di parametri ANY"

 

Ciao

Link al commento
Condividi su altri siti

se sei un programmatore ad alto livello devi capire che ANY è un puntatore a void . Quello che C/C++ si usa per caricare l'indirizzo di una variabile in un puntatore ossia "&" in awl è  P# etc etc.

L'area merker e l'area DB sono aree che il sistema operativo alloca in certi punti ben precisi e non sono da considerare come la memoria in C/C++

Link al commento
Condividi su altri siti

Per 0.0

 

" Apri la guida tramite il Simatic Manager e nel campo di ricerca dell'indice scrivi "Formato puntatore"  poi selezioni "tipo di parametri ANY" 

 

Facendo come hai detto non trovo nulla!Immagine.thumb.png.7e987355db359f9ea867f

 

Link al commento
Condividi su altri siti

Non devi aprire "guida a KOP", ma "Argomenti della guida".

Nella scheda "Indice" digita semplicemente any.

Quello che cerchi è nella prima riga.

Link al commento
Condividi su altri siti

Il tipo ANY è una "tabella" che devi compilare.

 

                                                     

  L     W#16#10 02                           //  Scrive nel Byte 0 il codice 10H ,  nel Byte 1 il codice 02H= BYTE, cioè che vuoi muovere dei BYTE
  T     LW [AR1,P#0.0]           

 

 

   L     #Len_Byte_Record_Car       // Scrive nel Byte 2 e Byte 3 , cioè nella 2° Word , il numero di BYTE che vuoi spostare 
   T     LW [AR1,P#2.0]

 

 

    L     #DB_Carr                              // Scrive nel Byte 4 e Byte 5 , cioè nella 3° Word , il numero della DB a cui i BYTE appartengono

    T     LW [AR1,P#4.0]

 

 

                                                           // in fine nei Byte 6 devi scrivere l'identificativo di area 16#84

 

                                                           // nei Byte 7,8,9  scrivi l'indirizzo da cui parte l'area che vuoi spostare

                                                           // indirizzo rappresentato come P#b.x ,

                                                           // dove  b= BYTE all'interno della DB

                                                           // mentre  x= BIT all'interno del BYTE

                                                           // Per l'offset bit x all'interno del byte hai 3 bit ....quindi dal bit0 , bit1, bit2

                                                           // nel tuo caso non consideri un offset a bit all'interno del byte, quindi i primi tre bit saranno zero

 

                                                           // Per l'offset a byte B all'interno della tua DB hai 16bit ....quindi puoi rappresentare un numero 0 ....65535

                                                           // Attenzione , prima caricare il numero dell'offset B nella Dword,

                                                          //  la sua rappresentazione deve essere shiftata a sinistra di 3 bit , questo è fatto con l'operatore SLD 3

                                                          

 

       L     #OffSet_Record_Car            
      SLD   3
      OD    DW#16#84000000             
      T     LD [AR1,P#6.0]                    

 

Spero di essere stato chiaro :)

 

 

Link al commento
Condividi su altri siti

I registri AR1 e AR2 sono registri della cpu , quindi con accesso più veloce rispetto alla ram e sono dedicati per caricare indirizzi , quindi sono puntatori.

Tuttavia , se ti trovi in situazioni difficili con diversi puntatori da gestire , puoi usare anche variabili di tipo DWORD (ram) .La sintassi  P# informa il processore che deve caricare un indirizzo nella DWORD piuttosto che in AR1 e/o AR2.Col vecchi omicrowin i puntatori erano gestiti sintatticamente come in C e non esistevano i registri AR1 o AR2 , ma tutto funzionava ugualmente bene .Il problema era che se avevi una tabella con N colonne dovevi gestire e sincronizzare N puntatori , uno per ogni colonna .Con step 7 invece la cosa la puoi gestire con strutture piu o meno complesse di dati e con SCL . Un array di struttura e' una tabella e tramite l'indice puoi fare tutto quello che vuoi e alla svelta senza avere brutte sorprese .comunque il formato implicito di puntatore lo devi usare quando passi una struttura dati ad una funzione 

Link al commento
Condividi su altri siti

Grazie davvero a tutti, mi sono chiarito molto le idee, poi usarli bene è un'altra cosa...

Salto la tua spiegazione è stata illuminante!

 

Un'altra cortesia, se invece che al BYTE avessi voluto puntare al BIT, ovvero avessi voluto che i tre bit finali XXX fossero  valorizzati (ad esempio 2)

io l'ho scritto in dei merker di appoggio, ovvio che poi andrebbe integrata nella sintassi dei puntatori, e ho visto che funziona: 

 

  L 2

  T MB 94                                      // Carico il valore 2

 

  L     100
  T     MW    90
   SLD   3
   OD    DW#16#84000000
   T     MD    96                                // Quindi tutto come prima fino a qui, solo "appoggiato in dei merker"

 

    L     MB    94                               
    L     MD    96
    OD    
    T     MD   100                             // OD per avere negli ultimi tre bit il valore 2 (binario 010)

 

 

Esiste una maniera più rapida per fare la stessa cosa? 

Immagino di si, ma essendo alquanto profano in materia di puntatori, ma avrete capito anche di AWL, mi chiedevo come si potesse scrivere il puntatore al bit!

 

Grazie ancora
 

 

 

 

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