Vai al contenuto
PLC Forum


Pointer


pippof77

Messaggi consigliati

Salve a tutti,ho un problema con il segmento allegato,non riesco a capire come funziona il pointer,qualcuno sa aiutarmi?

Modificato: da pippof77
Link al commento
Condividi su altri siti


Non sono riuscito ad allegare la il segmento quindi devo scriverlo

Auf db10

L#in0

T db525.dbw190

T #temp8

L stw

T#temp9

L dbb191

Slw 4

Lar1

L #temp9

T stw

L#temp8

L dbw [ar1,p#0.0]

==i

= m514.1

Non riesco a capire come funziona il pointer

Link al commento
Condividi su altri siti

L'argomento puntatori in S7-300 è stato trattato innumerevoli volte sul forum.

Ma, puntatori a parte, si inizia subito con un errore: nella prima riga viene aperto DB10, ma due righe dopo, con l'istruzione L DB525.DBW190, viene aperto il DB 525.

Le successive operazioni quindi verranno fatte sulle variabili di DB525, e non su quelle di DB10 come, probabilmente, era nelle intenzioni.

Poi non è che ci sia molto da dire.

Con l'istruzione L DBB191 si carica il valore del byte meno significativo della variabile DB525,DBW190, nella quale era stato caricato il valore di #in0, che viene copiato anche nella variabile temporanea #temp8.

La variabile stw è impossibile capire cosa contenga. Si vede solo che il suo valore viene copiato nella variabile temporanea #temp9.

Tornando al DBB191, viene fatto uno shift a sinistra di 4 bit. Questo serve perché i puntatori puntano sempre il bit. Se DBB191 contiene il numero di una word (16 bit), lo shift serve per puntare al primo bit della word indicata in DBB191.

Il valore così convertito viene depositato nel registro indirizzi 1.

Poi il valore di #temp9 viene ripassato a stw. E qui siamo in presenza di un bel mistero: appena prima viene scritto il valore di stw in #temp9, e subito dopo il valore di #temp9 viene scritto in stw.

Credo sia difficile trovare un'operazione più inutile.

Poi viene fatto un confronto tra il valore di #temp8 (che non è altro che il valore di #in0, che è stato scritto anche in DB525.DBW190) e il valore di una variabile (attenzione, del DB525 e non del DB10) indicata dal puntatore (il quale puntatore deriva da una parte del valore da confrontare).

Insomma, per capire qualcosa si dovrebbe almeno sapere quali erano le intenzioni di chi ha scritto questo codice, ma io vedo solo un pasticcio dietro l'altro. Dubito fortemente che possa funzionare.

Se il codice l'hai scritto tu, dovresti:

1) dare dei nomi alle variabili temporanee, in modo da capire a cosa dovrebbero servire

2) mettere dei commenti

3) visto che questo codice sicuramente non funziona, prova a dire cosa vorresti fare.

Link al commento
Condividi su altri siti

Per i motivi descritti nel mio precedente post, non mi pare che il problema sia solo nella riga del puntatore.

Qui c'è tutto il codice che non funziona.

Se tu avessi risposto alle mie domande, sarebbe ora più semplice aiutarti.

Comunque, limitando la risposta al puro utilizzo del puntatore, dobbiamo analizzare due operazioni: l'impostazione dell'indirizzo nel registro indirizzi, e l'operazione sulla variabile utilizzando il registro indirizzi.

L'impostazione dell'indirizzo nel registro indirizzi si effettua con l'istruzione LAR1, che carica nel registro indirizzi 1 (ci sono due registri indirizzi, ma ti consiglio di usare sempre solo il registro indirizzi 1) il valore contenuto nell'accumulatore 1.

Quindi, nel registro indirizzi 1 viene caricato il valore di DBB191 (Attenzione!!! DBB191 del DB525, e non del DB10) shiftato a sinistra di 4 bit.

Esempio: supponiamo tu voglia puntare alla 4ª word di un DB. In DBB191 (usato come indice) dovrai scrivere 3 (si parte da zero, quindi la 4ª word è la numero 3). Poi devi considerare che nel registro devi caricare l'indirizzo del primo bit della variabile che vuoi puntare (gli indirizzi in Step 7 sono sempre riferiti al bit). Visto che una word è composta da 16 bit, dovresti moltiplicare l'indice per 16. Ma, visto che uno spostamento a sinistra equivale a moltiplicare per 2, il modo più semplice risulta effettuare uno spostamento a sinistra di 4 posizioni (sarebbero 3 se tu volessi puntare al byte, e 5 se tu volessi puntare ad una variabile da 32 bit).

Ora, se il tuo indice era uguale a 3, nell'accumulatore dopo lo shift a sinistra di 4 bit troverai il valore 48 (HEX 00000030), che è l'indirizzo del primo bit della 4ª variabile del blocco.

E siamo arrivati a capire come caricare un indirizzo nel registro indirizzi. Ora dobbiamo capire come utilizzare il registro indirizzi.

Nel codice del tuo esempio troviamo l'istruzione

L dbw [ar1,p#0.0]

Come prima cosa, notiamo che si effettua una operazione (in questo caso una lettura, ma sarebbe lo stesso anche per una scrittura) su una variabile da 16 bit di un DB (DBW).

Dobbiamo però capire quale variabile, e di quale DB.

Bene. Il DB è semplicemente il DB aperto in questo momento (e, come spiegato nel mio precedente post, nel tuo esempio si tratta non del DB10, ma del DB525).

La variabile è quella il cui indirizzo è quello contenuto nel registro indirizzi 1 + un offset di 0. Questo è il significato di quello che c'è tra parentesi quadre [AR1, P#0.0].

Per esempio, scrivendo [AR1, P#2.0] avrei puntato alla word successiva (P#2.0 significa offset di 2 byte).

Questo è solo uno dei modi di utilizzare i puntatori in Step7 ma, per oggi, penso possa bastare.

Per finire, torno a ripetere che in quel segmento il problema non sono i puntatori, ma tutto il segmento.

Link al commento
Condividi su altri siti

ma scusate ,

scrivere:

auf db 10 // apro db 10

l 10 // carico il valore int 10 su accu 1

t dbw0 //trasferisco accu1 nella word 0

è uguale a scrivere

auf db 10 // apro db 10

l 10 //carico in accu 1 int 10

sld 4

lar1 // richiamo ar1

l dbw[ar1,p#0.0] // punto nella word 10 quindi bit 160 del db 10 o carico 10 come nr int sempre nella word 0?

Ho letto molti post e svariati esempi oltre ad aver provato con plc sim ma non mi è chiaro l' utilizzo del puntare all' bit di una db o merker ecc.

esempio se volessi in un db 10 costituito da 20 word formato int incrementare con l' impulso di m 0.0 partendo da 0 prima word,premo m0.0 e nella word 1 viene caricato 1, premo nuavamente m 0.0 e nella word 2 viene caricato 2 e cosi' via fino alla word 20 come potrei fare?

ho provato questo ma non funziona:

U M0.0

FP M0.1

SPBN A001

L #TEMP

L 1

T DBW

SLD 4

LAR1

L DBW[AR1,P#0.0]

T DBW[AR1,P#2.0]

A001 : NOP 0

Link al commento
Condividi su altri siti

ma scusate ,

scrivere:

auf db 10 // apro db 10

l 10 // carico il valore int 10 su accu 1

t dbw0 //trasferisco accu1 nella word 0

è uguale a scrivere

auf db 10 // apro db 10

l 10 //carico in accu 1 int 10

sld 4

lar1 // richiamo ar1

l dbw[ar1,p#0.0] // punto nella word 10 quindi bit 160 del db 10 o carico 10 come nr int sempre nella word 0?

Direi proprio di no.

Nella prima parte scrivi il valore 10 nella word 0 del DB10.

Nella seconda parte carichi il valore 10, fai uno shift a sinistra di 4 bit (quindi in accu1 ti ritrovi 160), metti accu1 in registro indirizzi 1, e vai a leggere il valore della variabile usando il puntatore. E qual è questa variabile? È la variabile numero 10 (ricorda sempre che si parte da zero, quindi l'undicesima variabile) del DB10.

Ho letto molti post e svariati esempi oltre ad aver provato con plc sim ma non mi è chiaro l' utilizzo del puntare all' bit di una db o merker ecc.

esempio se volessi in un db 10 costituito da 20 word formato int incrementare con l' impulso di m 0.0 partendo da 0 prima word,premo m0.0 e nella word 1 viene caricato 1, premo nuavamente m 0.0 e nella word 2 viene caricato 2 e cosi' via fino alla word 20 come potrei fare?

ho provato questo ma non funziona:

U M0.0

FP M0.1

SPBN A001

L #TEMP

L 1

T DBW

SLD 4

LAR1

L DBW[AR1,P#0.0]

T DBW[AR1,P#2.0]

A001 : NOP 0

Nel tuo codice non c'è nessun incremento dell'indice.

La variabile #TEMP non svolge nessuna funzione. Col fronte di salita di M0.0 vai a caricare sempre il valore 1 in una variabile non definita (in T DBW manca sia l'indicazione della variabile, sia quella del DB). Fai poi uno shift a sx di 4 bit e metti il risultato in AR1.

Poi copi il valore contenuto nella variabile puntata (che sarà sempre la seconda variabile, perché il puntatore non viene mai incrementato) e lo scrivi nella variabile successiva.

Quindi, supponendo che il DB aperto sia il DB10, non fai altro che copiare continuamente il valore di DB10.DBW2 in DB10.DBW4.

Link al commento
Condividi su altri siti

ciao e grazie per le risposte,

ho fatto molti tentativi e i registri gli ho capiti o comunque in base ai miei programmi rispondevano a quello che pensavo dovessero fare,ho fatto alcune prove con solo i puntatori p#...

es:

auf db 10 // apro db 10

u m0.0 // se bit m0.0 = 1

fp m0.1

spbn a001 // vado avanti altrimenti salto

L13 // carico 13

T dbw 0 // trasferisco in dbw 0

L p#0.0 // vado a dbb0 bit 0

T dbw 2 // trasferisco in dbw 2

a001 : nop 0

pensavo mi trasferisse 13 in dbw 0 e con il caricamento di p#0.0 me lo trasferisse anche in dbw 2 ma no è successo.

compare 13 solo in dbw 0 .

Con le mie prove ho trovato meno difficolta a capire gli ar che usare solamente l ' istruzione p#........

Link al commento
Condividi su altri siti

L p#0.0 // vado a dbb0 bit 0

T dbw 2 // trasferisco in dbw 2

Per il caricamento di 13 in DBW0, ok.

Per il resto, assolutamente no.

Con l'istruzione

L P#0.0

non fai nessuna operazione sui puntatori, ma carichi semplicemente in ACCU1 l'indirizzo P#0.0 (ovvero HEX 0000 0000).

Quindi, scrivi il valore 0 in DBW2.

Modificato: da batta
Link al commento
Condividi su altri siti

Grazie per la pazienza,

se io faccio

l p#2.0

t dbw0

carico 16 bit in dbw 0 e on line mi compare 16 sulla word 0, ma se io faccio

l 16

t dbw 0

sicuramente non è la stessa cosa ma non vedo il senso di caricare in accu 1 il p#...... quando con gli ar riesco a caricare il puntatore e anche a trasferire una certa word sull' ar gia precedentemente indirizzata.

grazie

Link al commento
Condividi su altri siti

sicuramente non è la stessa cosa

E invece è proprio la stessa cosa.

Anche caricare W#16#10, oppure 2#10000 porta allo stesso identico risultato.

Scrivendo L P#2.0 significa che carichi l'indirizzo del primo bit del byte 2, che è il 16º bit.

Scrivere L P#2.1 sarebbe come scrivere 17.

È solo una questione di praticità.

Sarebbe invece diverso scrivere L P#M2.0.

In questo caso infatti, oltre all'indirizzo caricheresti anche l'area di memoria (merker nell'esempio).

Nell'accumulatore ti troveresti il valore 83000010 in esadecimale.

Scrivendo invece L P#E2.0 il risultato sarebbe 81000010 Hex

L P#A2.0 --> 82000010 Hex

L P#DBX2.0 --> 84000010 Hex

L P#DIX2.0 --> 85000010 Hex

Link al commento
Condividi su altri siti

ok ma l' uso di L p#...... è cioè caricare in accu 1 serve solo se lo abbino ai registri o ha delle utilità anche da solo senza caricare i registri lo chiedo perche' ho fatto dei semplici programmi per capire usando solamente con gli ar e mi son trovato molto bene ad esempio:

auf db10 // apro db 10

l 10 // carico 10

sld 4 // moltiplico per 16 bit

lar1 //

l dbw[ar1,p#0.0] // carico il registro ar1+ ofset 0 quindi bit 160 o word 20

l 15 // trasferisco 15

t dbw[ar1,p#0.0] // nell' indirizzo word 20

in questo caso potevo usare l p#0.0 da qualche parte?

rigrazie

Link al commento
Condividi su altri siti

In parole povere P#... è un offset

Se hai AR1 impostato per puntare alla decima Word (non scrivo le istruzioni per concentrare l'attenzione sul p#...)

L DBW[AR1,P#0.0] leggerà la decima word

T DBW[AR1,P#2.0] scriverà la undicesima word

questo è molto comodo per leggere/scrivere varie Word senza dover ogni volta reimpostare AR1

Poi ci sono anche le istruzioni di incremento di AR1 che usano P#nnnn.n come offset per l'incremento.

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