Aiuto - Cerca - Utenti - Calendario
Versione completa: shiftare 2 dw
PLC Forum -> Forums automazione > AUTOMAZIONE > PLC > Siemens > Altro su PLC Siemens
holly
uso un s7-300
come faccio a far shiftare 2 double world una dietro l'altra?
mi spiego meglio....
ho bisogno di 64 bit e nn di 32 ora devo far shiftare la prima dw e nn voglio che l'ultimo bit venga perso,ma il bit che esce deve entrare nell'altra dw
ma nn so come fare!!!
walterword
prova a vedere se trovi qualcosa su "ruota" bit o byte o word o dword
l'istruzione rotazione non ti fa perdere nessun bit , non so se c'e' per dword
al limite esegui 2 operazioni ruota word nella dword
controlla nelle funzioni se c'e' qualcosa del genere
ciaose nella procaperdi qualcosa vedi se riesci a copiare la o le word su altre word di appoggio e poi ricomporre il tutto
ifachsoftware
Non conosco l'S7300 nello specifico ma in genere per tali operazioni devi gestire il bit di carry facendo due shift consecutivi
beppeconti
Non mi risulta che puoi lavorare a 64bit con l'S7 300.
Lavorando a 32bit pui utilizzare le funzioni SLD o SRD, il bit che estrai dalla Dword lo leggi nel bit di stato A1.
Da qui poi devi copiare questo bit nell'altra Dword.

CIAO
jumpier
Fai semplicemente delle operazioni OR con word di appoggio; mi spiego meglio: supponiamo che il tuo valore di partenza è 1011101011111101 e si trova in DB10.DBW0.
Il tuo prgramma ti richiede (per esempio) uno shift a destra di 4 posizioni; in questo modo perderesti i primi 4 bit.
Allora tu fai un bel shift a sinistra di 12 e ottieni 1101000000000000 e cioè l'equivalente dei 4 bit che "sforavano" nella word precedente (o successiva a secondo della direzione dello shift). Il risultato lo scrivi ad esempio in DB10.DBW10. Poi riprendi il valore di partenza DB10.DBW0 e questa volta fai il tuo shift a destra di 4 posizioni ottenendo 0000101110101111; il risultato lo poni in DB10.DBW12. A questo punto in due word consecutive hai il tuo valore di partenza shiftato a destra di 4 posizioni senza perdere neppure un bit biggrin.gif biggrin.gif !!!
Attenzione ad eventuali inversioni di byte di cui Siemens è famoso ................
Fai lo stesso ragionamento su una o più dword e dovrebbe andare .... premetto che magari esiste una bella funzione per fare il tutto; io ti ho risposto senza controllare l'help in linea ma solo a senso.

Ciao
Federico Milan
Se non hai probleme di sorta potresti ragionare così, però presuppone che le parole siano ordinate in bigendian e non litleendian ... :

vedi i tuoi 64_bit tutti di seguito, quindi ... se devi shiftare a sinistra di n_bit

partendo da sinistra trali il bit 64-n nella posizione 64, e procedi così per 64 volte, aggiungendo ovviamente nelle posizioni smile.gif è semplice da fare con i puntatori ...

oppure potresti ragionare così (spero di non dire castronerie visto che ho un po' di mal di testa ...)

Shifti la parola meno significatica a sinistra di n volte, memoriazzandoti su di un appoggio tutti i bit che escono, a questo punto schifti a sinistra la parola iù significativa di N e ci sommi la parola creata con i bit che sono usciti e il gioco è fatto!
walterword
....se il tutto lo vuoi un a word
metti in OR le due word su un'altra word finale
....pardon tu vuoi preservare due dword consecutive
be comunque come dice federico non e' male
seno devi usare altre dword di appoggio , shiftare ,salvare, usare qualche maschera or o and , poi copiare
ci sono diverse tecniche.
ci vorrebbe un disegnino su carta per comprendere il movimento ch e vuoi fare
ciao
walterword
...non vorrei complicarti la vita
ma se queste due dword le vedi come 64 bit
magari in un array di booleani????
puoi spostare come vuoi a destra a sinistra
sopra sotto
se usi SCL (magari ce l'hai) e' come il pascal
puoi indicizzare e con cicli for_next o while _do
fare quello ch e vuoi
o seno in awl con i puntatori
seno devi mascherare, copiare,controllare, e' piu macchinoso
holly
mi spiego meglio.....
fate finta di avere una catena di montaggio.....
aevete dei pezzi che poi subiranno lavorazioni varie.....
ora volete rappresentare la catena con 2 DW ogni pezzo vale un bit....
il pezzo arriva, il mio sensore sente il pezzo e manda a 1 il primo bit della prima DW0 00000000000000000000000000000001 ora insieme al pezzo arriva anche il gancio che lo regge e un sensore mi fa shiftare la DW0 di un posto 00000000000000000000000000000010 la situazione dopo 10 pezzi sarà la seguente 00000000000000000000011111111110 mettendo il caso che il mio pezzo sia arrivato nella posizione che
|_________________________________|

a me interessa ora prendo il bit corrispondente e farò attivare un qualcosa............
logicamente se dovesse arrivare il gancio senza pezzo nn farà nulla .......
capite bene che questo funziona se i miei pezzi che devono subire la lavorazione sono 32 e se le fasi di lavorazioni sono finite....
ma se le fasi di lavorazione fossero il doppio ed i pezzi ad entrare fossero il doppio come faccio? nn voglio perdere l'ultimo bit lo vorrei trasferire nella DW successiva... la DW4
ma nn so proprio come fare........
walterword
-setti il primo bit della nuova dword aggiunta
-dopodiche resetti l'ultimo bit della prima dword che si e' fatta piena
-in questo modo non hai perso l'informazione
-a questo punto hai l'ultimo bit della primq dword libero
-quidni puoi far shiftare ancora il malloppo verso di esso .
-poi fai shiftare nella seconda dword cosi hai il primo bit della seconda word
vuoto per poterci settare un'altro ultimo bit della prima dword .
understand?

cool.gif
beppeconti
Se quello che vuoi è costruire un registro da 64bit a scorrimento per fare delle sequenze, potresti utilizzare la seguente tecnica:
nella prima Dword, MD0 ci sono i primi 32 bit del registro ( i meno significativi ).
nella seconda Dword, MD4 ci sono gli altri 32 bit del registro ( i più significativi ).
...............MD4.............................MD0.................
64-----------------------33 32--------------------------1

Le istruzioni in AWL per eseguire uno sorrimento a SX di 1 bit sono le seguenti:

// faccio scorrere a SX i 32 bit ( 33...64 ) della seconda DWord
L MD 4
SLD 1
T MD 4

// faccio scorrere a SX i 32 bit ( 1...32 ) della prima Dword
L MD 0
SLD 1
T MD 0

// se il bit più significativo della prima DWord prima dello scorrimento a SX valeva 1 ...
SPP agg1
SPA end

// ... lo scrivo come meno significativo nella seconda DWord
agg1: L MD 4
L 1
OD
T MD 4

end: bea


CIAO
valter
Vediamo se ho capito bene :

U impulso_shift //impulso per far shiftare le doppie word di un passo
SPBN END
L MD4 //seconda doppia word
SLD1
T MD4

U M0.7 //appoggio il bit in uscita della prima doppia word
=M7.0 //e la appoggio al bit di ingresso sulla seconda doppia word

LMD0 //prima doppia word
SLD1
TMD0
U #bit_input //input dello shift register
=M3.7

END: NOP 0

Se non era quello che chiedevi mi scuso ..... ma ero di fretta

ciao
Valter
JumpMan
CITAZIONE
Walterword dice:
...non vorrei complicarti la vita
ma se queste due dword le vedi come 64 bit
magari in un array di booleani????
puoi spostare come vuoi a destra a sinistra
sopra sotto...in awl con i puntatori
...



Secondo me ha ragione, potresti fare un FC più o meno così

CODICE
//Variabili da inserire nella tendina:
INPUT  Impulso : BOOL;      // Ingresso attivazione scorrimento
TEMP  #IndiceLoops: INT
//Fine variabili da inserire nella tendina:


   UN #Impulso
   BEB

   AUF DB10            // Supponiamo di creare il registro in DB10 DBB20...27
   LAR1 P#20.0         // Imposta AR1 per puntare al bit DBX20.0

   L 64                // <--NR. DI BIT DEL REGISTRO
L1: T #IndiceLoops
   U DBX[AR1,P#0.0]    // Legge stato bit nnn.n
   R DBX[AR1,P#0.0]    // (se a 1 lo resetta)
   +AR1 P#0.1          // Incrementa AR1 per puntare al bit successivo
   = DBX[AR1,P#0.0]    // Imposta il bit successivo (nnn.n+1)
   L #IndiceLoops      // Finchè #IndiceLoops > 0
   LOOP L1             //   decrementa #IndiceLoops e Salta a L1
   BE




Oppure (meglio) ti crei un FB con la sua DB d'istanza nella quale memorizzi l'array di bit


CODICE
//Variabili da inserire nella tendina:
INPUT  Impulso : BOOL;      // Ingresso attivazione scorrimento
INPUT  NrBits : INT;        // Quantità di bit del registro
TEMP   IndiceLoops : INT;   // Indice loops
STAT   Bit : ARRAY  [0 .. 99 ] OF  BOOL // Array di 100 Bits del registro
//Fine variabili da inserire nella tendina:

   UN #Impulso
   BEB

   L #NrBits           // <--NR. DI BIT DEL REGISTRO (imposti valore 0-99 quando richiami l'FB)
L1: T #IndiceLoops
   U DBX[AR1,P#0.0]    // Legge stato bit nnn.n
   R DBX[AR1,P#0.0]    // (se a 1 lo resetta)
   +AR1 P#0.1         // Incrementa AR1 per puntare al bit successivo
   = DBX[AR1,P#0.0]    // Imposta il bit successivo (nnn.n+1)
   L #IndiceLoops      // Finchè #IndiceLoops > 0
   LOOP L1  //   decrementa #IndiceLoops e Salta a L1
   BE

In questo modo, nel resto del programma puoi interrogare i bit così:

U "NomeDB".Bit[n]

Spero di non aver sbagliato la sintassi in quanto l'ho scritta col blocco note e non con Step 7.

Ciao
walterword
come ti dicevo io
usa un array
una cosa: dovrebbe esserci un fronte di salita
dopo l'ingresso che ti fa eseguire queste operazioni
altrimenti le eseguirai ad ogni ciclo di scansione
perdendo il vero input
ciao
albrecht
Ho preso spunto dal codice di "JumpMan" per crearmi questo FB. Spero che possa essere utile per qualcuno!

CODE
FUNCTION_BLOCK "fb_shift_generico"
TITLE =shift generico
VERSION : 0.1


VAR_INPUT
sposta_shift : BOOL ; //fronte positive sposta il shift
SetBit : BOOL ; //setta primo bit
Reset : BOOL ; //resetta shift intero
NrBits : INT ; //min = 2 , max = 1000
NrShift : INT ; //Numero di spostamenti
END_VAR
VAR
Bit : ARRAY [0 .. 999 ] OF BOOL ;
FP_shift : BOOL ;
END_VAR
VAR_TEMP
IndiceLoops : INT ;
IndiceLoopsShift : INT ;
Indirizzo_Inizziale : DWORD ;
Indirizzo : DWORD ;
IndirizzoFinale : DWORD ;
IndirizzoPrecedente : DWORD ;
TempBit : BOOL ;
END_VAR
BEGIN
NETWORK
TITLE =iniziallizza i puntatori

L P#0.0;
L 6;
SLD 3;
+D ;
T #Indirizzo_Inizziale; // carica indirizzo inizziale del shift (6.0)

L #NrBits;
+D ;
T #IndirizzoFinale; // carica indirizzo finale del shift (indirizzo iniziale + nr. di bit)

NETWORK
TITLE =setta primo bit nel shift


U #SetBit;
S DIX 6.0; // imposta il primo bit nel shift register


NETWORK
TITLE =resetta tutto il shift

U #Reset;
SPBN shft; // salta al "shft" in caso di ingresso reset non attiva
L #Indirizzo_Inizziale;
T #Indirizzo; // carica indirizzo inizziale nel indirizzo

L #NrBits; // <--NR. DI BIT DEL REGISTRO (imposti valore 2-1000 quando richiami l'FB)
L3: T #IndiceLoops;
R DIX [#Indirizzo]; // (se a 1 lo resetta)

L #Indirizzo;
L P#0.1; // Incrementa indirizzp per puntare al bit successivo
+D ;
T #Indirizzo;
L #IndiceLoops; // FinchË #IndiceLoops > 0
LOOP L3; // decrementa #IndiceLoops e Salta a L1



NETWORK
TITLE =

shft: U #sposta_shift;
FP #FP_shift;
SPBN end; // se l'ingresso "sposta shift" va a uno (fronte) continua, se no salta fino a "end"

L #NrShift;

L2: T #IndiceLoopsShift; // numero di shift da fare

L #IndirizzoFinale;
T #Indirizzo;


L #NrBits; // <--NR. DI BIT DEL REGISTRO (imposti valore 2-1000 quando richiami l'FB)
L1: T #IndiceLoops;

L #Indirizzo;
L L#1;
-D ;
T #IndirizzoPrecedente;

SET ;
U DIX [#IndirizzoPrecedente]; // Legge stato bit nnn.n
= DIX [#Indirizzo]; // Imposta il bit successivo (nnn.n+1)
R DIX [#IndirizzoPrecedente]; // (se a 1 lo resetta)

L #Indirizzo;
L P#0.1; // Incrementa indirizzo per puntare al bit successivo
-D ;
T #Indirizzo;

L #IndiceLoops; // FinchË #IndiceLoops > 0
LOOP L1; // decrementa #IndiceLoops e Salta a L1
L #IndiceLoopsShift;
LOOP L2;


end: NOP 0;



END_FUNCTION_BLOCK


PLCforum Staff
Questa discussione e' chiusa, la puoi trovare nella nuova sezione PLC raggiungibile a questo indirizzo plc.plcforum.it
PLCforum Staff
Questa discussione e' chiusa, la puoi trovare nella nuova sezione PLC raggiungibile a questo indirizzo plc.plcforum.it
Questa è la versione 'lo-fi' del forum. Per visualizzare la versione completa con molte più informazioni, formattazione ed immagini, per favore clicca qui.