Vai al contenuto
PLC Forum

Partecipa anche tu alla Live su Youtube martedì 28/01/2025 per festeggiare i 24 anni di PLC Forum

Per ulteriori informazioni leggi questa discussione: https://www.plcforum.it/f/topic/326513-28012025




shiftare 2 dw


Messaggi consigliati

Inserito:

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 non di 32 ora devo far shiftare la prima dw e non voglio che l'ultimo bit venga perso,ma il bit che esce deve entrare nell'altra dw

ma non so come fare!!!


Inserita: (modificato)

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

Modificato: da walterword
ifachsoftware
Inserita:

Non conosco l'S7300 nello specifico ma in genere per tali operazioni devi gestire il bit di carry facendo due shift consecutivi

Inserita:

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

Inserita:

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 :D:D !!!

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'. in linea ma solo a senso.

Ciao

Federico Milan
Inserita:

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 :) è 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!

Inserita: (modificato)

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

Modificato: da walterword
Inserita:

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

Inserita:

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 non 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? non voglio perdere l'ultimo bit lo vorrei trasferire nella DW successiva... la DW4

ma non so proprio come fare........

Inserita: (modificato)

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

B)

Modificato: da walterword
Inserita:

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

Inserita:

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

Inserita: (modificato)
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ì

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

Modificato: da JumpMan
Inserita:

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

  • 8 years later...
Inserita:

Ho preso spunto dal codice di "JumpMan" per crearmi questo FB. Spero che possa essere utile per qualcuno!

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


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