coquinati Inserito: 3 maggio 2014 Segnala Share Inserito: 3 maggio 2014 ho la massima necessita di imparare ad usare i puntatori con grande dimestichezza, avevo gia una infarinatura ( li usavo in maniera un pò banale) , ho deciso di riprendere in mano la situazione da zero per cercare di formarmi in maniera piu corretta possibile , mi sono imbattuto su un esrcizio di Federico Milan su puntatori a 32bit. che consiste che su un blocco dati di 10 variabili di tipo byte me ne analizza una per una, e mi crea la media di 2 varibili per volta e il risultato lo inserisce nella prima , ecco il programmino : L 10 // numero di loop max next: T #CONT_LOOP L 10 ITD -D L 8 *D //CALCOLO L'INDRIZZO BIT DA PUNTARE(costante 1) T #PUNT L 8 +D T #PUNT_1 //CALCOLO IL SECONDO INDRIZZO BIT DA PUNTARE (+8)(costante2) AUF DB 2 L DBB [#PUNT] //punto il primo L DBB [#PUNT_1] // punto il secondo +I //sommo le 2 costanti L 2 /I //divido per 2 T DBB [#PUNT] //trasferisco il risultato nella prima costante L #CONT_LOOP LOOP next la cpu mi entra in stop, subito mi da un errore ( da buffer di diagnistica) ERRORE LUNGHEZZA DI CAMPO DI LETTURA, copio il link della guida dell'evento :Cause: · Il valore indirizzato dall'indirizzo di accesso è escluso, completamente o in parte, dal campo di operandi ammissibile (grandezza specifica della CPU). · A causa di un errore di calcolo dell'indirizzo, il valore indirizzato è > 65535. In caso di indirizzamento indiretto può risultare, con un calcolo errato, un valore maggiore di 65535. Questo valore non può più essere registrato correttamente nell'informazione dettagliata dell'evento. Come indirizzo di accesso verranno così registrati e visualizzati il valore 0 per la S7-300 e per la S7-400 il valore calcolato modulo 65535 Rimedio: · Scegliere l'indirizzo di accesso in modo tale che il valore indirizzato sia compreso interamente nel corrispondente campo di operandi ammissibile. · Controllare il programma utente leggendo questo errore da quanto dice step 7 il mio puntatore ha un indirizzo troppo grande...ma sicuramente l'ho inteso male.....il vostro . è ben accetto,, grazie in anticipo , e buonanotte Link al commento Condividi su altri siti More sharing options...
beppo Inserita: 3 maggio 2014 Segnala Share Inserita: 3 maggio 2014 (modificato) Ciao. Dunque, ragionandoci un attimo si vede che carichi 10 in ACC1 e lo trasferisci in #CONT_LOOP, poi carichi di nuovo 10 in ACC1 di conseguenza il vecchio valore di ACC1 va in ACC2, che è 10, dopo trasformi il valore 10 in ACC1 da intero a doppio intero, poi sottrai il valore di ACC1 dal Valore di ACC2, qui ovviamente il tuo risultato sarà sempre 0, 10-10=0 Quindi alla fine avrai sempre 0 su #PUNT e 8 su #PUNT1 Alla fine fine l'istruzione LOOP non l'ho mai usata su S7, quindi non so se è corretto. Per evitare che la CPU ti vada in Stop, carica l'OB121, così puoi vedere il tuo ciclo girare e capire meglio cosa succede e trovare il problema. P.S. Certo che a quell'ora della notte non deve essere facile ragionare sui puntatori... :P Modificato: 3 maggio 2014 da beppo Link al commento Condividi su altri siti More sharing options...
walterword Inserita: 3 maggio 2014 Segnala Share Inserita: 3 maggio 2014 impara SCL , i puntatori non servono a nula quando si ha un linguaggio chiaro e semplice come SCL o ST Link al commento Condividi su altri siti More sharing options...
coquinati Inserita: 3 maggio 2014 Autore Segnala Share Inserita: 3 maggio 2014 qui ovviamente il tuo risultato sarà sempre 0, 10-10=0 in teoria non è cosi , perchè l'istruzione loop conta nel mio caso da 10 a 1 e il numero del loop lo tiene sempre presente attraverso la variabile #CONT_LOOP.esempio da quello che ho capito: 10-10=0 punto alla variabile 0 del mio blocco dati 10-9=1 punto alla variabile 8(sempre inteso in bit) e cosi via.. poi arriva a l'ultimo loop che farà 10-1 =9 punta alla varibile bit 72.0 poi chiaramente prima di saltare decrementa il loop vede 0 e non salta più. Per evitare che la CPU ti vada in Stop, carica l'OB121, così puoi vedere il tuo ciclo girare e capire meglio cosa succede e trovare il problema. provato , e vedo che mi punta la variabile 0.0 e 1.0 ma si blocca... sembra che non riesce puntarmi...strano perchè non vedo niente di errato nella sequenza. P.S. Certo che a quell'ora della notte non deve essere facile ragionare sui puntatori... lo so purtoppo io parto nel studiare calcolando il tempo che mi serve senza nessun imprevisto. e dopo va finire che sono costretto a stare li ore per cercare di capire un problema,,e non ho ancora concluso nulla impara SCL , i puntatori non servono a nula quando si ha un linguaggio chiaro e semplice come SCL o ST si walter proprio ieri ho visto esempi di puntatori su questo linguaggio , e devo dire che sembrava quasi banale usarli, però non tutti i programmatori lo usano , come nel mio caso se mi capita un programma da analizzare in AWL non mi resta che studiare, Link al commento Condividi su altri siti More sharing options...
walterword Inserita: 3 maggio 2014 Segnala Share Inserita: 3 maggio 2014 fai prima a rifare l aparte di codice in SCL , l'importante e' sapere cosa devi fare piuttosto che come funzionano i puntatori , Link al commento Condividi su altri siti More sharing options...
JumpMan Inserita: 3 maggio 2014 Segnala Share Inserita: 3 maggio 2014 A mio avviso c'è qualcosa che non va in quell'esempio. Tieni presente chenio contatore loop viene decrementato dalla cpu da 10 fino a 0, le prime istruzioni sottraggono 10 a questo contatore, quindi il primo giro lo fa correttamente perché 10-10=0 quindi viene effettuata la media tra il byte 0 e il byte 1, ma il secondo giro il contatore loop è a 9, sottraendo 10 farebbe -1 che il sistema interpreta come 65535 intero unsigned. Quando prova a caricare il byte 65535 va in stop. Link al commento Condividi su altri siti More sharing options...
JumpMan Inserita: 3 maggio 2014 Segnala Share Inserita: 3 maggio 2014 scusa l'ortografia, sti tablet del piffero, chenio = che il Link al commento Condividi su altri siti More sharing options...
JumpMan Inserita: 3 maggio 2014 Segnala Share Inserita: 3 maggio 2014 Il programma corretto è: L 10 // numero di loop max next: T #CONT_LOOP L L#10 L #CONT_LOOP -D L 8 *D //CALCOLO L'INDRIZZO BIT DA PUNTARE(costante 1) T #PUNT L 8 +D T #PUNT_1 //CALCOLO IL SECONDO INDRIZZO BIT DA PUNTARE (+8)(costante2) AUF DB 2 L DBB [#PUNT] //punto il primo L DBB [#PUNT_1] // punto il secondo +I //sommo le 2 costanti L 2 /I //divido per 2 T DBB [#PUNT] //trasferisco il risultato nella prima costante L #CONT_LOOP LOOP next Link al commento Condividi su altri siti More sharing options...
JumpMan Inserita: 3 maggio 2014 Segnala Share Inserita: 3 maggio 2014 (modificato) C'è anche un altro modo di usare i puntatori: AUF DB 2 L P#DBX 0.0 // Prepara AR1 per puntare al primo byte LAR1 L 10 // numero di loop max next: T #CONT_LOOP L DBB [AR1,P#0.0] // Leggo primo byte L DBB [AR1,P#1.0] // leggo secondo byte +I // sommo le 2 costanti L 2 /I // divido per 2 T DBB [AR1,P#0.0] // trasferisco il risultato nel primo byte +AR1 P#1.0 L #CONT_LOOP LOOP next Questo fa esattamente la stessa cosa, per me è molto più chiaro... Posso anche modificrlo rapidamente per lavorare con word anzichè bytes: AUF DB 2 L P#DBX 0.0 // Prepara AR1 per puntare al primo word LAR1 L 10 // numero di loop max next: T #CONT_LOOP L DBW [AR1,P#0.0] // Leggo primo word L DBW [AR1,P#2.0] // leggo secondo word +I // sommo le 2 costanti L 2 /I // divido per 2 T DBW [AR1,P#0.0] // trasferisco il risultato nel primo word +AR1 P#2.0 L #CONT_LOOP LOOP next Modificato: 3 maggio 2014 da JumpMan Link al commento Condividi su altri siti More sharing options...
JumpMan Inserita: 3 maggio 2014 Segnala Share Inserita: 3 maggio 2014 (modificato) ... posso scrivere i risultati in un altra DB (DB3) lasciando inalterati i valori in DB2: AUF DB 2 AUF DI 3 L P#DBX 0.0 // Prepara AR1 per puntare al primo word LAR1 L 10 // numero di loop max next: T #CONT_LOOP L DBW [AR1,P#0.0] // Leggo primo word L DBW [AR1,P#2.0] // leggo secondo word +I // sommo le 2 costanti L 2 /I // divido per 2 T DIW [AR1,P#0.0] // trasferisco il risultato nel primo word +AR1 P#2.0 L #CONT_LOOP LOOP next Modificato: 3 maggio 2014 da JumpMan Link al commento Condividi su altri siti More sharing options...
beppo Inserita: 4 maggio 2014 Segnala Share Inserita: 4 maggio 2014 in teoria non è cosi , perchè l'istruzione loop conta nel mio caso da 10 a 1 e il numero del loop lo tiene sempre presente attraverso la variabile #CONT_LOOP Ah ok, sinceramente l'istruzione loop non l'avevo neanche mai vista su Step7 ... posso scrivere i risultati in un altra DB (DB3) lasciando inalterati i valori in DB2: Bello questo codice. Leggero ma molto funzionale. Link al commento Condividi su altri siti More sharing options...
coquinati Inserita: 5 maggio 2014 Autore Segnala Share Inserita: 5 maggio 2014 jumpman mi scuso se rispondo ora ma è stato un weekend difficile , solo ora riesco dedicare un po di tempo a step 7, riguardo al primo esempio ho capito, un mio errore nel tenere conto degli accumulatori, ho risolto subito, caricato il programma , ma resta in stop , ora ho visto che arriva a puntare il bit 2.0( piccolo miglioramento), sul db sto utilizzando un array da 1 a 10 , ma il problema non dovrebbe essere qua a parere mio, essendo la prima volta che li uso mi sto aspettando di tutto.. ho letto che come io uso i puntatori sarebbe un metodo molto spartano, il metodo più efficace e come hai detto te è nell'esempio 2 , cioè usare i registri del accumulatore che se non sbaglio sono (AR1 e AR2), cosa che mi sono messo subito a studiare ma il sonno ha preso il sopravvento ( sembra un argomento molto difficile) quindi rinvio tutto a domani e vedo se riesco scrivere una sequenza utilizzando questi ultimi come hai fatto te. grazie Link al commento Condividi su altri siti More sharing options...
JumpMan Inserita: 5 maggio 2014 Segnala Share Inserita: 5 maggio 2014 ciao ma come non ti funziona, li ho provati tutti prima di postare e funzionano, compreso l'#8 Hai fatto copia-incolla del codice? AR1 (AR2 non lo usare) non è niente di difficile, è un registro a 32 bit che funziona come i puntatori che usi tu solo che ha delle istruzioni dedicate in più e una costante offset regolabile a piacere (molto utile per spostare il puntatore avanti/indietro senza variarlo). Link al commento Condividi su altri siti More sharing options...
coquinati Inserita: 7 maggio 2014 Autore Segnala Share Inserita: 7 maggio 2014 rispondo ora perchè mi sono ritirato nel poco tempo libero nei meandri della camera a studiare,e sono riuscito a capire qualcosa forse L P#DBX 0.0 // Prepara AR1 per puntare al primo wordLAR1 praticamente carichi il valore del pointer di accu 1 nel registro AR1 . L DBB [AR1,P#0.0] // Leggo primo byte qua carichi ar1 che è preimpostato ad aprire l'indirizzo in un blocco dati +AR1 P#2.0 qua sommi due byte, su AR1, quindi poi riprendi da qua: L DBW [AR1,P#2.0] // Leggo primo wordL DBW [AR1,P#4.0] // leggo secondo word la cosa che mi manda più in confusione che prima lavoravo in BIT . ora devo usare dei BYTE, AR1 (AR2 non lo usare) non è niente di difficile, è un registro a 32 bit che funziona come i puntatori che usi tu solo che ha delle istruzioni dedicate intendi operazioni matematiche ? una costante offset regolabile a piacere in questo caso :P#0.0 ? scusa se ti faccio tutte queste domande , e che voglio essere sicuro, i puntatori mi puntano paura grazie mille per ora, ti ho inviato un MP. grazie ancora e notte a PLC Forum Link al commento Condividi su altri siti More sharing options...
JumpMan Inserita: 8 maggio 2014 Segnala Share Inserita: 8 maggio 2014 (modificato) Credo che tu abbia capito il mio esempio. Le istruzioni di AR1 sono LAR1, TAR1 che servono solo per leggere e scrivere il registro (come L e T fanno per ACCU 1) L'istruzione +AR1 è molto utile perchè permette di incrementare il registro di uno "step" che può essere: - di un bit (P#0.1) per puntare al bit successivo - di un byte (P#1.0) per puntare al byte successivo - di 2 byte (P#2.0) per puntare alla word successiva - di 4 byte (P#4.0) per puntare alla dword successiva - di n bytes (P#n.0) per puntare dove si vuole... Come potrai notare l'istruzione non influenza ACCU 1 e quindi si può usare tranquillamente nei loop senza preoccuparsi di andare a sporcare gli ACCU (e quindi i calcoli in corso) Non ho capito cosa ancora non ti è chiaro, forse il fatto che i puntatori siemens contengono sia l'indirizzo del byte che quello del bit ? La parte che va a finire in AR1 sono i bytes 2-3-4-5 nell'immagine qui sotto (è simile anche per gli altri puntatori e questo spiega perchè si usa l'operazione SLD 3 , per far posto ai 3 bit usati per il puntamento a bit) p.s. ho visto ora il tuo messaggio privato, ti ho risposto Modificato: 8 maggio 2014 da JumpMan Link al commento Condividi su altri siti More sharing options...
coquinati Inserita: 9 maggio 2014 Autore Segnala Share Inserita: 9 maggio 2014 Come potrai notare l'istruzione non influenza ACCU 1 e quindi si può usare tranquillamente nei loop senza preoccuparsi di andare a sporcare gli ACCU (e quindi i calcoli in corso) infatti, ma obbligatoriamente io dovro specificare attraverso l'accu la mia area di memoria per esempio: L P#DBX 0.0 // Prepara AR1 per puntare al primo word LAR1 oppure: L P#MW 0.0 // Prepara AR1 per puntare al primo byte LAR1 Non ho capito cosa ancora non ti è chiaro, forse il fatto che i puntatori siemens contengono sia l'indirizzo del byte che quello del bit ? si , perche io sul mio primo esempio usavo un puntatore specificando solo l'indirizzo in bit, ora devo usare usare i byte.bit , ero convinto che su siemens i puntatori funzionassero solo a bit,per esempio voglio punTare al byte 10, scrivo: L DBB [#80] //punto invece se uso quesa istruzione: L P#DBX 0.0 // Prepara AR1 per puntare al primo word LAR1 posso fare cosi: L DBB [AR1,P#10.0] . guardando la tabella che mi hai allegato è riferita a un formato pointer, che necessita di un indirizzo BITE.BIT , e sono quelli(sempre se ho capito) contrasegnati dalla lettera P# ,quindi la prima istruzione che usavo (L DBB [#80] //punto ) non è un formato pointer, ma un puntataore qualsiasi La parte che va a finire in AR1 sono i bytes 2-3-4-5 nell'immagine qui sotto (è simile anche per gli altri puntatori e questo spiega perchè si usa l'operazione SLD 3 , per far posto ai 3 bit usati per il puntamento a bit) sinceramente essendo alle prime armi con i puntatori non ho mai avuto modo di utillizare questa istruzione, praticamente azzera il 5 byte,ma per riuscire a fare cosa? ma il 3 byte resta inutilizzato? comunque mi scuso per le mia domande stupide, e che voglio imparare, ti ringrazio per la diponibiltà , ho risposto amche io a mp, grazie e notte! Link al commento Condividi su altri siti More sharing options...
JumpMan Inserita: 9 maggio 2014 Segnala Share Inserita: 9 maggio 2014 L P#DBX 0.0 // Prepara AR1 per puntare al primo word LAR1 Meglio cosi (non tocchi ACCU1): LAR1 P#DBX 0.0 // Prepara AR1 per puntare al primo word L DBB [#80] Questa è errata, casomai: L DBB[MD80] ma solo dopo aver caricato in MD80 una costante pointer, questo si può fare con una costante pointer: L P#5.0 T MD80 // prepara MD80 per puntare al byte 5 L DBB[MD80] // leggo il byte DBB5 Oppure con delle istruzioni L 5 SLD 3 T MD80 L DBB[MD80] // leggo il byte DBB5 Lo stesso risultato lo ottieni usando il registro AR1: LAR1 P#5.0 L DBB[AR1, P#0.0] // leggo il byte DBB5 ma con il vantaggio di leggere e scrivere anche altro variando l'offset: L DBB[AR1, P#1.0] // leggo il byte DBB6 T DBB[AR1, P#2.0] // scrivo il byte DBB7 sinceramente essendo alle prime armi con i puntatori non ho mai avuto modo di utillizare questa istruzione, praticamente azzera il 5 byte,ma per riuscire a fare cosa? ma il 3 byte resta inutilizzato? questo te lo spiego un altra volta, ora devo andare, ciao Link al commento Condividi su altri siti More sharing options...
coquinati Inserita: 10 maggio 2014 Autore Segnala Share Inserita: 10 maggio 2014 ciao jump man. devo ammettere che quello di scrivere la media delle due variabili su un altro blocco dati e davvero comoda, molto più chiaro come esercizio. Questa è errata, casomai: L DBB[MD80] noto che anche siemens sugli esempi usa una doppia parola, questo perchè usi un puntatore a 32 bit? grazie. Link al commento Condividi su altri siti More sharing options...
walterword Inserita: 10 maggio 2014 Segnala Share Inserita: 10 maggio 2014 (modificato) i due registri dei puntatori AR1 e AR2 sono piu veloci in quanto registri vicini al processore. Puoi usare comunque qualsiasi doppiaword DW che essendo in ram implica qualche cosa in piu in termini di tempo , comunque irrisori per applicazioni plc L'indirizzo di una variabile contenuto in un puntatore altro non e' che un numero di offset nella memoria la cui dimensione e' memorizzabile in una DW Modificato: 10 maggio 2014 da walterword Link al commento Condividi su altri siti More sharing options...
coquinati Inserita: 10 maggio 2014 Autore Segnala Share Inserita: 10 maggio 2014 L'indirizzo di una variabile contenuto in un puntatore altro non e' che un numero di offset nella memoria la cui dimensione e' memorizzabile in una DW ora penso di avere capito , visualizzando la tabella postata da jump man si nota che utilizza 32 bit, per quello DW , o puntatore a 32 bit. L P#5.0 T MD80 // prepara MD80 per puntare al byte 5 L DBB[MD80] // leggo il byte DBB5 praticamente cosi prepari il puntatore a ricevere indirizzi a bit , giusto? grazie a walter e jumpman Link al commento Condividi su altri siti More sharing options...
JumpMan Inserita: 11 maggio 2014 Segnala Share Inserita: 11 maggio 2014 praticamente cosi prepari il puntatore a ricevere indirizzi a bit , giusto? no! il puntatore è sempre byte.bit Se carica byte o bit o word o dword dipende solo dalle istruzioni successive: L DBB[MD80] U M[MD80] L DBW[MD80] L DBD[MD80] Link al commento Condividi su altri siti More sharing options...
coquinati Inserita: 12 maggio 2014 Autore Segnala Share Inserita: 12 maggio 2014 (modificato) ma quindi hai scelto 5 per puntare solo al byte 5, volendo scrivo L p#1.0 e punto al byte 1. L 5 SLD 3 facendo cosi passi i 3 bit del indirizzo bit al byte 4 del pointer , cosi punti a Byte 5 grazie ragazzi Modificato: 12 maggio 2014 da coquinati Link al commento Condividi su altri siti More sharing options...
yepes Inserita: 18 giugno 2014 Segnala Share Inserita: 18 giugno 2014 Discussione utilissima per comprendere il concetto di puntatore ed il loro utilizzo. Link al commento Condividi su altri siti More sharing options...
Messaggi consigliati
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 accountAccedi
Hai già un account? Accedi qui.
Accedi ora