Vai al contenuto
PLC Forum


Settare Il Bit Di Una Word


Porto

Messaggi consigliati

Buon giorno.

Chedo consiglio a Voi del Forum.

Premetto che provengo dalla programmazione Omron, dove, a mio avviso (qui lo dico e qui lo nego, dato che per la maggior parte si tratta di pareri personali e affinità di linguaggio) le operazioni su word, bit, byte e digit sono più versatili.

Vengo al dunque: mi voglio costruire un FB "Step_Ciclo", il quale dovrà ricercare all'interno di una word di transizione di stati, il primo bit alto.

E per questo ho già visto delle funzioni che usano il loop e le shift word.

Con l'indice così calcolato, mi voglio settare il bit di un'altra word.

Come si fa?

O meglio, e più in generale, dato un indice (es. n), che posso inserire attraverso una supervisione o da dato di processo che va da 0 a 15 (o da 1 a 16), come faccio a settare il corrispondente bit di una word?

Mi viene in mente l'istruzione di schift:

carico in accumulatore 1

L 1

SLW 1

e itero per n volte, dove n è il bit che voglio settare, ma questa procedura mi sembra un pò macchinosa...

Non mi sembra esistano funzioni dedicate, secondo Voi c'è una procedura più semplice?

Grazie e buona sera.

Link al commento
Condividi su altri siti


Buon giorno.

Partendo da un FB che usavo, ho creato qualcosa che funziona, ma vi chiedo un paio di cose che non mi sono molto chiare, data la mia non dimestichezza con l'uso dei registri AR1 e AR2 e loro complicanze:

U #StStepNextEn //controllo se ho StStepNextEn

SPBNB En_1 //altrimenti non sono abilitato ai cicli

TAR1 #AR1_Tmp // carico il contenuto di AR1 nella variabile temporanea

TAR2 #AR2_Tmp

LAR1 #P_TrSt // carico in AR1 il valore del puntatore a TrSt

L W [AR1,P#0.0] // faccio scorrere la word a sinistra

TAW

T #AppWd

T #Debug_W1

L 16

Loop: T #IndexLoop

L #AppWd

SLW 1 // faccio scorrere la word a sinistra di 1 bit

T #AppWd

SPZ JMP // se il bit è zero, salto il settaggio

// ***********************************************************************************

*
LAR1 #P_St // carico in AR2 il valore del puntatore a St

*
TAR1 #TempDwd_1

L #TempDwd_1

T #TempDWd

L 0 // carico zero in ACCU-1

*
T W [AR1,P#0.0] //azzero la word di stato

L #IndexLoop

L 1

-I

*
+AR1 //sommo al puntatore di Word St, l'offset

*
S [AR1,P#0.0] //dato dall'indice della word TrSt

JMP: L #IndexLoop //setto così il bit interessato

LOOP Loop

L 1

T #Debug_W2

LAR1 #AR1_Tmp //Ripristina il contenuto dei registri

LAR2 #AR2_Tmp

En_1: NOP 0

Allora, inizialmente (qui *) avevo usatio AR2, perché non volevo usare lo stesso indice AR1 che usavo per la word di transizione.

E qui la CPU andava in SF, pur eseguendomi correttamente il codice.

Ho inserito una word di appoggio e visualizzata sulla VAT come contatore mi dava un indirizzo inesiste: P#4000 e rotti....

Come mai?

Inserisco il sorgente qualora qualcuno volesse darci un occhiata o usarlo per i suoi sviluppi.

Ringrazio Batta e voi del forum per i vostri post da cui ho tratto a piè mani!

Buona giornata.

Link al commento
Condividi su altri siti

Come accade molto spesso, la soluzione è più semplice del previsto.

E, per trovarla, bastava portare il cursore sull'istruzione "SLW" e premere F1 per accedere all'aiuto in linea e accorgersi che (cito dall'aiuto stesso):

SLW (Fai scorrere parola a sinistra) fa scorrere il contenuto di ACCU 1-L verso sinistra, bit per bit. Le posizioni dei bit, che risultano vuote in seguito all'operazione di scorrimento, vengono alimentate con zeri. Il bit traslato per ultimo viene caricato nel bit di stato A1. Il numero di bit nella misura del quale operare lo scorrimento viene indicato dall'operando <numero> oppure da un valore specificato nell'accumulatore 2-L-L.

Cosa significa? Significa che se scrivo:

SLW 3

il contenuto dell'accumulatore 1 verrà shiftato a sx di tre bit

Ma se scrivo:

SLW

senza indicare un numero, l'accumulatore 1 verrà shiftato a sx del numero di posizioni indicate dal byte basso dell'accumulatore 2.

Quindi, per effettuare uno shift di un nmero variabile di bit, non servono operazioni strane o loop. Basta, molto semplicemente, indicare prima l'entità dello shift.

Esempio:

L MB20

L MW22

SLW

T MW24

Significa che il contenuto di MW22 verrà shiftato a sx del numero di posizioni indicate in MB10. Il risultato verrà posto in MW24.

Ovviamente, se in MB20 carico un numero superiore a 15 (31 in caso di shift su dword con istruzione SLD), otterrò un azzeramento della variabile.

Link al commento
Condividi su altri siti

Grazie Batta!

Sempre puntuale, preciso ed efficace!

mi piace di più questa soluzione, rispetto che usare i registri AR1 e AR2, anche se penso il risultato finale, a parte il tempo ciclo di esecuzione, più lungo usando i puntatori, sia lo stesso.

DeiI puntatori penso non ne possa fare a meno, perché le word di stato e di transizione, sono delle UDT ( questo non posso modificarlo, perché tutti i programmi che elaboriamo, per garantire una certa uniformità, sono strutturati cos ì) il loop nemmeno (almeno sulla prima parte), perché, quello che voglio fare, è ricercare il bit a 1 più basso, e con questo settare il corrispondente bit di stato a 1. quello che posso fare è eventualmente spostare la scrittura della statu word fuori dal loop. (accetto qualsiasi pareri sull'analisi, non appena poso, posto il codice riveduto)

Quello che non riesco a capire è come mai, se uso AR2, al posto di AR1, la CPU si arrabbia e si accende il led rosso SF, e nello stato mi segnala un errore di accesso alle aree di memoria, pur senza errori o stop durante l'esecuzione delle istruzioni...

Buona notte.

Link al commento
Condividi su altri siti

Nelle FB, AR2 è meglio non usarlo perchè contiene il puntatore alla DB di istanza.

Se lo devi usare, salva prima il contenuto e ripristinalo alla fine della FB.

Ciao

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