Vai al contenuto
PLC Forum


Puntatori Awl


zoz

Messaggi consigliati

Ciao a tutti, sono nuovo del forum.

Colgo l'occasione per chiedervi aiuto su una cosa. Sto imparando a programmare in AWL e ho un disperato bisogno di utilizzare i puntatori,(cosa da me piuttosto sconosciuta). Purtroppo sul manuale AWL simens non dice grandi cose. Sapete dove posso trovare una dispensa o qualche articolo a riguardo?

Mi interessano sopratutto per le operazioni di calcolo, incremento e lettura e scrittura su DB.

Se potete aiutarmi, vi ringrazio.

Link al commento
Condividi su altri siti


Grazie! La guida la conoscevo già.. Poco esauriente a mio avviso.

Vi chiedo un altra cosa. Ho bisogno di puntare a un bit di un byte di una word di periferia e resettarlo.

Come posso fare con i puntatori?

Link al commento
Condividi su altri siti

Ho bisogno di puntare a un bit di un byte di una word di periferia e resettarlo.

Come posso fare con i puntatori?

Perchè vuoi complicare le cose? Per resettare un bit di una word basta usare una maschera in AND con la word.

Link al commento
Condividi su altri siti

Si, hai ragione. Ma ho iniziato da poco a programmare in Awl e non mi viene facile l'utilizzo dei puntatori. Ecco perchè chiedevo un' aiuto con i puntatori :-) era didattico..

ad ogni modo presumo non si possa puntare a un bit di una word di periferia, S7 non me lo permette... Mah...

Link al commento
Condividi su altri siti

I puntatori tipicamente puntano ad un indirizzo di memoria. La memoria nei sistemi Siemens, ma non solo, è organizzata a bytes, pertanto i puntatori puntano ad un byte.

Se non ricordo male, ci sono istruzioni specifiche in S7 (in microwin sicuramente) che settano, resettano e testano uno o più bits di un singolo byte.

Modificato: da Livio Orsini
Link al commento
Condividi su altri siti

Mi sembra qui ci sia un errore di fondo.

le word di periferia non sono memorizzate nell'immagine di processo, quindi non è assolutamente possibile modificarne i valori; esse si possono solo leggere e scrivere con istruzioni di lettura e scrittura immediata, come byte, word o dword ... nulla per i bit. Il mascheramento andrebbe fatto in locale, su delle memorie di appoggio.

Link al commento
Condividi su altri siti

Se con "bit di un byte di una word di periferia" intendi un bit di un canale analogico (PEW o PSW, per esempio), allora, come dice mubeta, devi accontentarti di lavorare a byte, word o dword.

Se invece intendi semplicemente un ingresso o una uscita digitale, puoi agire direttamente sul bit.

Detto questo, c'è da precisare che in Step7 i puntatori non puntano il byte, ma il bit.

esempi:

U E[MD100]

U M[DB10.DBD4]

= A[MD104]

Dove MD100 è la variabile che contiene l'indirizzo dell'ingresso che si desidera leggere.

Tenendo presente, come detto sopra, che si deve impostare l'indirizzo dl bit, l'indirizzo si calcola moltiplicando x8 (o con shift a sinistra di 3 bit) il numero del byte, e sommando il numero del bit all'interno del byte.

Esempi:

E0.5 --> 0*8 + 5 = 5

E12.2 --> 12*8 + 2 = 98

Link al commento
Condividi su altri siti

..c'è da precisare che in Step7 i puntatori non puntano il byte, ma il bit

Questo non lo sapevo! E' un caso più unico che raro.

Modificato: da Livio Orsini
Link al commento
Condividi su altri siti

Per essere più precisi, il formato Pointer, lungo 6 byte, è composto come segue.

Partendo dal byte più significativo, secondo lo standard Motorola o Big Endian:

byte 0 e 1: numero del DB

byte 2: codice area di memoria

byte 3-4-5: indirizzo.

Dei byte 3-4-5 i 5 bit più significativi (dal bit 19 al bit 23) sono sempre a zero. I successivi 16 bit (dal bit da 3 al bit 18) contengono l'indirizzo del byte. I 3 bit meno significativi (dal bit 0 al bit 2) contengono l'indirizzo del bit.

Di fatto risulta molto più comodo considerare che l'indirizzo punti direttamente al bit.

Negli esempi del mio precedente post si notano principalmente due cose:

1) ho utilizzato un puntatore a 32 bit e non a 48 bit, come sopra descritto. In questo modo si perde l'informazione del numero del DB, che in questo caso non è rilevante.

2) il byte che dovrebbe contenere l'area di memoria (byte 2 nel caso di puntatore a 48 bit, byte 0 nel caso di puntatore a 32 bit) è posto semplicemente a zero. Questo è possibile perché l'area di memoria è indicata in modo esplicito nell'istruzione. Scrivendo "U E[MD0]" si definisce in modo inequivocabile l'area degli ingressi.

Altro modo (più completo ed elegante) di lavorare con i puntatori, consiste nell'utilizzare i registi degli indirizzi AR1 e AR2. Ma l'argomento, oltre ad essere già stato ampiamente trattato nel forum, è piuttosto lungo.

Nella sezione "Tips & Tricks - PLC esempi di programmazione" ci sono anche alcuni miei piccoli lavori che, al di là della funzione principale svolta che potrebbe non interessare, utilizzano i puntatori, con tanto di spiegazioni.

Link al commento
Condividi su altri siti

  • 2 weeks later...

Ma per esempio, se volessi scrivere una word che è nella db1 sulla db2, in modo ripetitivo, come potrei fare? Allora, io ho ragionato così. Ditemi dove sbaglio per piacere.

L DB1.DBW 0 //Carico la DBW0 del DB1

ITD //La converto in 32bit

L L#2 // carico una costante a 32 (Perche sul db 2 voglio fare un salto ogni 2byte)

*D // Moltiplico

SLD 3 //shifto a SX per avere il formato puntatore

L P#0.0 // carico un puntatore 0.0

+D // Lo sommo al valore precedente

LAR1 // metto tutto il risultato in AR1

AUF DB 2 // apro db2

T DBW [AR1,P#0.0] // Trasferisco sulla word che dovrebbe essere 2 con un offset di 0.0

Unico problema... Non funziona. Perchè? Cosa sbaglio? Dove cade il mio ragionamento? ho un disperato bisogno di comprendere sti puntatori, ma non ne salto fuori. Perfino il simulatore mi sta scongiurando, non ne può più....

Link al commento
Condividi su altri siti

mi sembra che tu stia facendo confusione fra dati e indirizzi.

// preparo l'indirizzo:
AUF DB2
L L#2  // carico una costante a 32 (Perche sul db 2 voglio fare un salto ogni 2byte)
SLD 3 //shifto a SX per avere il formato puntatore
L P#DBX0.0 // carico un puntatore della posizione 0.0 di DB2
+D // Lo sommo al valore precedente
LAR1 // metto tutto il risultato in AR1, il registro AR1 punterà a DBX2.0

// trasferisco il dato
L DB1.DBW 0 //Carico la DBW0 del DB1
AUF DB2
T DBW [AR1,P#0.0] // Trasferisco sulla word che dovrebbe essere 2 con un offset di 0.0

Modificato: da rguaresc
Link al commento
Condividi su altri siti

Ti ringrazio per l'aiuto... Poi se si vuole farlo in modo continuo, basta incrementare AR1 di 2 e metterci un loop per le volte desiderate, tutto insieme a un bel salto. Ho appena provato e funziona alla grande. Figata.

Comunque hai proprio ragione, faccio confusione con indirizzi e dati. Consigli per levarmi questo problema??? :D :D :D

STO AWL comincia a piacermi! :-))))

Link al commento
Condividi su altri siti

  • 1 year later...

Buongiorno, sapete dirmi se cè un manuale o qualsiasi guida fatta bene su come programmare con i puntatori, capirne come funzionano e che cosa ci si può fare. La guida che è presente nel sito non mi soddisfa molto.

Grazie attendo risposta

Link al commento
Condividi su altri siti

Ciao,

non mi ero reso conto di questa discussione quindi ho lanciato un'altra discussione simile e mi scuso... Pongo il mio problema quì.

Batta ma come utilizzo i puntatori a 48 bit?

Cioè io voglio puntare con AR1 ad una DB e con AR2 ad un'altra DB ed utilizzarli contemporaneamente senza richiamare ogni volta gli AUF. Ma come fare???

L'obiettivo è puntare ai dati in questo modo:

L B [AR1,P#0.0]

T B [AR2,P#0.0]

In ciclo poi modifico direttamente AR1 ED AR2 incrementandoli a mio piacere...

Modificato: da antstan
Link al commento
Condividi su altri siti

Antstan, da quel che so io (e vado un po' a tentoni) i registri indirizzo a disposizione sono almeno due... quindi...


//carico il DBx nel primo registro indirizzi

AUF DBx

LAR1

//carico il DBy nel secondo registro indirizzi

AUF DBy

LAR2

//adesso Ar1 e Ar2 sono impostati basta chiamare con gli offset

//copio il primo bite di DBx nel secondo di DBy

L DBB[Ar1,P#0.0]

T DBB[Ar2,P#1.0]

Link al commento
Condividi su altri siti

invece non è così.

Come ho potuto capire i registri non contengono informazioni sul DB da puntare.

Per tale motivo se AR1 deve puntare al DB X ed AR2 al DB Y quando si richiama un puntatore diverso si deve rifare l'AUF. Mi sembra strano ma i test da me effettuati...

Scrivo un esempio su cui ho fatto dei test, prendo dei puntatori come ingresso alla FB:

L P##P_Buffer // Variabile puntatore

LAR1

L W [AR1,P#0.0]

T #T_Db_Buffer // Variabile intera

L D [AR1,P#2.0]

LAR1

TAR1 #T_P_Buffer // DWord

L P##P_BlockIn // Variabile puntatore

LAR1

L W [AR1,P#0.0]

T #T_Db_BufferIn // Variabile intera

L D [AR1,P#2.0]

LAR1

TAR1 #T_P_BufferIn // DWord

// così ho salvato le mie locazioni ora quando mi servono faccio così

LAR1 #T_P_Buffer

LAR2 #T_P_BufferIn

Auf #T_Db_Buffer

L B [AR1, P0.0]

T Byte_App

Auf #T_Db_BufferIn

L Byte_App

T B[AR2,P0,0]

Questo è l'unico modo in cui sono riuscito a farlo andare...

Attendo notizie da chi è più esperto di me.

Link al commento
Condividi su altri siti

antstan effettivamente mi devo ricredere ho provato del semplicissimo codice:

FUNCTION "TestPun" : VOID

TITLE =

VERSION : 0.1



VAR_INPUT

  DBX_num : INT ;	

  DBY_num : INT ;	

END_VAR

VAR_OUTPUT

  Somma : INT ;	

END_VAR

VAR_TEMP

  Buffer : INT ;	

END_VAR

BEGIN

NETWORK

TITLE =


	  L	 #DBX_num; //prendo il numero del DBX

	  T	 #Buffer; // lo metto in un buffer temporaneo (non so bene perché devo fare così, ma o così o chiodi...)


	  AUF   DB [#Buffer]; // apro il DB num X

	  L	 P#DBX 0.0; // carico l'indirizzo zero

	  LAR1  ; // salvo l'indirizzo zero del DB num X in AR1 (in realtà vedremo che non è così... salvo solo lo scostamento dal primo dato del DB)...


	  L	 #DBY_num;

	  T	 #Buffer;


	  AUF   DB [#Buffer];

	  L	 P#DBX 0.0;

	  LAR2  ;


	  L	 DBW [AR1,P#0.0];

	  L	 DBW [AR2,P#0.0];

	  +I	;

	  T	 #Somma;


END_FUNCTION
Poi ho provato:

FUNCTION "TestPun2" : VOID

TITLE =

VERSION : 0.1


VAR_INPUT

  DBX_num : INT ;

  Merker : WORD ;

END_VAR

VAR_OUTPUT

  Somma : INT ;

END_VAR

VAR_TEMP

  Buffer : INT ;

END_VAR

BEGIN

NETWORK

TITLE =

	  L	 #DBX_num; //prendo il numero del DBX

	  T	 #Buffer; // lo metto in un buffer temporaneo (non so bene perché devo fare così, ma o così o chiodi...)

	  AUF   DB [#Buffer]; // apro il DB num X

	  L	 P#DBX 0.0; // carico l'indirizzo zero

	  LAR1  ; // salvo l'indirizzo zero del DB num X in AR1 (in realtà vedremo che non è così... salvo solo lo scostamento dal primo dato del DB)...

	  L	 P##Merker;

	  LAR2  ;

	  L	 DBW [AR1,P#0.0];

	  L	 MW [AR2,P#0.0];

	  +I	;

	  T	 #Somma;

END_FUNCTION


Poi ho provato anche:

FUNCTION "TestPun3" : VOID

TITLE =

VERSION : 0.1



VAR_INPUT

  DBX_num : INT ;	

  Merker : WORD ;	

END_VAR

VAR_OUTPUT

  Somma : INT ;	

END_VAR

VAR_TEMP

  Buffer : INT ;	

END_VAR

BEGIN

NETWORK

TITLE =


	  L	 P##Merker;

	  LAR1  ;


	  L	 #DBX_num; //prendo il numero del DBX

	  T	 #Buffer; // lo metto in un buffer temporaneo (non so bene perché devo fare così, ma o così o chiodi...)


	  AUF   DB [#Buffer]; // apro il DB num X

	  L	 P#DBX 0.0; // carico l'indirizzo zero

	  LAR2  ; // salvo l'indirizzo zero del DB num X in AR2 (in realtà vedremo che non è così... salvo solo lo scostamento dal primo dato del DB)...


	  L	 DBW [AR2,P#0.0];

	  L	 MW [AR1,P#0.0];

	  +I	;

	  T	 #Somma;


END_FUNCTION

Infine ho chiamato le due funzioni in OB1:


	  CALL  "TestPun"

	   DBX_num:=6

	   DBY_num:=7

	   Somma  :=MW480


	  CALL  "TestPun2"

	   DBX_num:=6

	   Merker :=MW482

	   Somma  :=MW484


	  CALL  "TestPun3"

	   DBX_num:=6

	   Merker :=MW482

	   Somma  :=MW486

Ed ho analizzato i risultati:

DB6.DBW 0 = 123

DB7.DBW 0 = 456

MW480 = 912 (!!!!) mi doveva venire 123+456=579; mentre in realtà mi ha sommato due volte DB7.DBW 0 infatti: 456+456=912

DB6.DBW 0 = 123

MW482 = 777

MW484 = 900 //ovvero con un DB e un merker non crea problemi (uso effettivamente le aree di memoria che volevo)

MW486 = 900

Allora sembra proprio che passando il secondo DB al registro indirizzi 2 sovrascrivo anche il registro indirizzi 1... suppongo quindi che per puntare al DB il PLC utilizzi qualche altro registro che è uno solo.... ovvero può accedere un solo DB per volta (da cui bisogna richiamare sempre AUF DB ogni volta si cambia DB...)

Guardando lo stack infatti sia AR1 che AR2 hanno lo stesso valore

P#DBX0.0 = 84000000 hex (la prima area di memoria di un generico DB)

mentre a sinistra c'è una voce che indica il DB aperto...

Suppongo quindi che l'indirizzamento a DB sia così fatto PUNDB->ARx

con AUF si setta PUNDB che è uno solo...

Non si finisce mai di imparare...

E' giusto, quello che scrivo?

Link al commento
Condividi su altri siti

Nota:

Dice Batta

Per essere più precisi, il formato Pointer, lungo 6 byte, è composto come segue.

Partendo dal byte più significativo, secondo lo standard Motorola o Big Endian:

byte 0 e 1: numero del DB

byte 2: codice area di memoria

byte 3-4-5: indirizzo.

Poi noi sappiamo che AR1 e AR2 sono a 32 bit (4 byte)...

quindi è chiaro che i byte 0 e 1 non sono memorizzati in AR1 e/o AR2... da cui il problema...

Link al commento
Condividi su altri siti

Concordo su tutto,

In realtà la paura è che il continuo uso degli AUF appesantisca la funzione...

Ho letto che si possono "aprire" 2 DB in contemporanea, 1 come Auf DB XXX e l'altro come istanza AUF DI YYY ma non sono riuscito ad utilizzarli...

In ogni caso Batta ha affermato:

Negli esempi del mio precedente post si notano principalmente due cose:

1) ho utilizzato un puntatore a 32 bit e non a 48 bit, come sopra descritto. In questo modo si perde l'informazione del numero del DB, che in questo caso non è rilevante.

2) il byte che dovrebbe contenere l'area di memoria (byte 2 nel caso di puntatore a 48 bit, byte 0 nel ca...

Quindi probabilmente esiste un modo per utilizzare puntamenti a 48 bit ma io non l'ho trovato...

Forse quando tornerà dalle vacanze...

Link al commento
Condividi su altri siti

L'unico modoo è quellodii usare le db di istanza, ricorda che le word non saranno DBW ma ben DIW per i dati della db aperta come istanza

Modificato: da l.bonacini
Link al commento
Condividi su altri siti

imparate SCL , il linguaggio strutturato "ST" che si integra in step 7

I puntatori sono ormai cosa remota .

Con SCL si posso no fare lavori complessi ed in pochi minuti , con i puntatori ci verrebbero settimane per raggiungere lo scopo

ciao

Walter

Link al commento
Condividi su altri siti

Con SCL si posso no fare lavori complessi ed in pochi minuti , con i puntatori ci verrebbero settimane per raggiungere lo scopo

ciao

In SCL lavorare con i puntatori è molto semplice, ma affermare che la differenza va da pochi minuti a settimane, mi pare un tantino esagerato, non credi?

Poi noi sappiamo che AR1 e AR2 sono a 32 bit (4 byte)...

quindi è chiaro che i byte 0 e 1 non sono memorizzati in AR1 e/o AR2... da cui il problema...

Se in una funzione (FC o FB) dichiari un parametri in ingresso di tipo POINTER e, quando richiami la funzione, a questo parametro colleghi una variabile, in realtà passi alla funzione l'indirizzo di tale variabile.

All'interno della funzione puoi scrivere:

	  L	 P##Adr_IN

	  LAR1  


	  L	 W [AR1,P#0.0]

	  T	 #Nr_DB


	  L	 D [AR1,P#2.0]

	  T	 #Adr_32bit

Dove:

- "Adr_IN" è il parametro in ingresso di tipo POINTER

- "Nr_DB" è una variabile di tipo INT contenente il numero del DB (byte 0 e 1 della variabile "Adr_IN"). Se la variabile passata alla funzione non appartiene ad un DB, il valore sarà zero.

- "Adr_32bit" è una variabiel di tipo DINT o DWORD contenente l'indirizzo della variabile, area di memoria compresa (byte 2-3-4-5 della variabile "Adr_IN")

Nello stesso modo, si possono passare ad una funzione puntatori in formato ANY (10 byte).

Link al commento
Condividi su altri siti

ti diro' che in molti impianti se on fosse esistito SCL avrei sicuramente cambiato mestiere ...

i predecessori che lavoravano in awl hanno fatto sempre lavori limitati e chi ha voluto esagerare si e' trovato nel guano , oltre al fatto che poi la manutenibilità nel futuro e' pressoch' nulla .

Impianti con tracking , magazzino autmatici con inserimento , modifica , recupero quote , nomi di prodotti o tipi (stringhe) d confrontare , cercare , formattare ....creare stringhe da inviare a stampanti , ricevere in seriale , gestire comunicazioni tcp/ip con aggeggi di ogni sorta ...

In awl non ne vieni fuori più e per progettare il tutto ci vogliono giorni e poi e poi giorni in messa in servizio e poi giorni per rifare ....quindi settimane .

Se invece devi puntare ad una tabella di valori int o dint o real allora ce la puoi fare .

Non servovo a niente i puntatori , tutti gli ambienti di sviluppo plc , e anche i microprocessori , hanno il linguaggio ad alto livello ST , siemens ha SCL , ok si paga ma non e' poi cosi caro il prezzo considerando la quantità di codice prodotto ,testato e messo in funzione .

La cosa importante e' saper gestire o avere fantasia nel creare la corretta base di dati , e qui step7 mette a disposizione meravigliosi DB che possono essere composti da array di strutture, da array di array di strutture ect .

Quindi il lavoro principale e' l'analisi del sistema e mettere bene a fuoco cosa e come si deve fare.

Per il resto con SCL poi si fa alla svelta , molto alla svelta .

Non capisco come mai nel 2012 si voglia ancora ostinarsi a programmare i puntatori in awl ,forse per dimostrare le proprie capacità o una remota nostalgia ....non vi capisco ...

Con questo senza nulla togliere alla vostra professionalità .

In RSLogix , allen bradley , Schneider , Matsushita , Beckhoff , Vago ect ect c'e' sempre un tool ST .

Codesys ha ST , Logic Lab ha ST , hanno tutti il linguaggio ST e lo usano tutti in maniera veloce e funzionale .

I soft plc che sono ospitati da pc si programmano in ST , C , C++

La concentrazione del programmatore deve focalizzarsi sul cosa fare , fare alla svelta , rifare il meno possibile , riportare funzioni in altri progetti e ragionare , pensare programmando .

Poi le macchine lavorano epr noi , compilano , arrangiano e sistemano ....

bisogna pensare che l'automazione ormai e' una nicchia dell'informatica se la si fa a certi livelli , e di conseguenza adattarsi .

Devo ammettere che la gestione puntatori in s7-200 e' molto piu veloce di step7 , in s7-200 e' come in C , "&" e " * " ...

ciao

Walter

Link al commento
Condividi su altri siti

  • Livio Orsini locked this discussione
Ospite
Questa discussione è chiusa alle risposte.
×
×
  • Crea nuovo/a...