Vai al contenuto
PLC Forum


Bit Di Una Word


Alessiooo

Messaggi consigliati

ciao a tutti

avrei bisogno di una vostra mano per costruire una piccola funzione in grado di contare quanti bit di una word si trovano a 1 , e mettere il risultato dentro un'altra word.

esempio contare i bit a 1 di mw50 e depositare il risultato in mw52..

grazie mille

Link al commento
Condividi su altri siti


Dipende cosa vuoi fare , se e' una cosa che ti serve una volta e mai piu' e non ti serve indicizzabile ,

il sistema migliore e' e piu' stupido e' :

metti zero in mw200

se m50.0 = 1 add 1 a mw200

se m50.1 = 1 add 1 a mw200

ecc ecc

alla fine in MW 200 hai quanti bit sono a 1

se lo vuoi parametrizzare , il principio di funzionamento e' uguale ma devi indicizzare m50.0 come m[md300] dove in MD300 hai 50.0 ( 50x8+0)

ovviamente devi looppare il sw incrementando md300 di 1 per 16 volte ( partendo da 0 )

Luca

Link al commento
Condividi su altri siti

Potresti fare anche così:

            
// Azzero word contatore bit                        
      L     0
      T     "wContatoreBit"
            
      L     16
L1:   T     "wIndiceLoop"
      L     "wDaEsaminare"
      SRW   1
      SPP   inc
      SPA   L2
            
// Incremento word contatore bit            
inc:  L     "wContatoreBit"
      L     1
      +I    
      T     "wContatoreBit"
            
L2:   L     "wIndiceLoop"
      LOOP  L1                                    // Esegue 16 loops
            
            
// In questo punto "wDaEsaminare" contiene il nr. di bit a 1

Link al commento
Condividi su altri siti

Jumpman

non ho verificato se il tuo programma funzioni oppure no , ma "credo" che tra le istruzioni:

L "Wda esaminare" e SRW 1 sia necessario inserire l'istruzione TAW,

e dopo che hai fatto lo shift devi risalvare la word da esaminare shiftata altrimenti verifichi solo e sempre lo stesso bit della word.

Link al commento
Condividi su altri siti

ciao rgazzi

alla fine ho fatto all'antica.... non tanto bello ma funzionante...

cioè con il fronte di salita di ogni singolo bit aggiungo uno e sottraggo uno con il fronte di discesa.....

grazie milleeeeee

Link al commento
Condividi su altri siti

cioè con il fronte di salita di ogni singolo bit aggiungo uno e sottraggo uno con il fronte di discesa.....

Onestamente, di tutti i metodi proposti, questo mi sembra il meno funzionale.

Prova a vedere se ti va bene la funzione BITSUM (FC99) della Siemens.

La trovi in StandardLibrary --> TI-S7 Converting Blocks.

In ingresso si aspetta una DWORD, ma se tu devi contare i bit di una WORD, ti basta appoggiare la WORD a una DWORD (magari locale) prima di darla in pasto alla funzione.

Esempio:

L MW10

T MD12

oppure:

L MW10

T #DW_Appoggio //Variabile locale di appoggio

Link al commento
Condividi su altri siti

Steu hai ragione, ho scritto in fretta, manca un istruzione dopo lo shift, inoltre è meglio appoggiarsi su un'altra word.

Il TAW non sono convinto che serva, perchè SRW shifta tutti i 16 bit verso destra ed ogni volta che "esce" un bit va a 1 il bit di stato A1 condizionando il salto

SPP.

// Azzero word contatore bit                        
      L     0
      T     "wContatoreBit"

// Appoggio la word da esaminare
      L     "wDaEsaminare"
      T     "wAppoggio"
            
      L     16
L1:   T     "wIndiceLoop"
      L     "wAppoggio"
      SRW   1
      T     "wAppoggio"
      SPP   inc
      SPA   L2
            
// Incremento word contatore bit            
inc:  L     "wContatoreBit"
      L     1
      +I    
      T     "wContatoreBit"
            
L2:   L     "wIndiceLoop"
      LOOP  L1                                    // Esegue 16 loops
            
            
// In questo punto "wContatoreBit" contiene il nr. di bit a 1

Modificato: da JumpMan
Link al commento
Condividi su altri siti

Se non vuoi usare BIT_SUM, puoi usare la funzione "BitCnt" che ho appena fatto.

In ingresso a questa funzione puoi dare una variabile, la prima variabile di un array o di una struttura, l'indirizzo della variabile, o anche la variabile, l'array o la struttura in modo simbolico.

La funzione non carica il valore della variabile passata, ma il suo indirizzo.

Altro parametro richiesto in ingresso è la lunghezza in byte dell'area di cui si vogliono contare i bit a 1.

Restituisce, in formato INT, i bit a 1 contati.

Non sono effettuati, all'interno della funzione, controlli sulla validità dei dati passati.

Sarà cura del programmatore assicurarsi che tali dati siano corretti.

Per esempio, la lunghezza deve essere almeno 1 byte. Più quest'area è grande, più sarà lungo il tempo di elaborazione della funzione.

ATTENZIONE

Compilando il sorgente si genera la funzione FC113.

Se tale funzione esiste già nel vostro progetto, verrà irrimediabilmente sovrascritta.

Fatene quello che volete. La funzione è completamente libera e ben descritta, utile quindi (almeno così spero) anche per didattica, non solo per un suo eventuale utilizzo sul campo.

Come sempre, non mi assumo nessuna responsabilità derivante dal suo utilizzo e, unica cortesia che chiedo, non cambiate il nome dell'autore.

Grazie.

post-83993-0-13802300-1391271485_thumb.j

P.S. anche eventuali commenti, sia buoni che cattivi, sarebbero graditi :)

Link al commento
Condividi su altri siti

Fatene quello che volete. La funzione è completamente libera e ben descritta, utile quindi (almeno così spero) anche per didattica, non solo per un suo eventuale utilizzo sul campo.

Come sempre, non mi assumo nessuna responsabilità derivante dal suo utilizzo e, unica cortesia che chiedo, non cambiate il nome dell'autore.

Flavio, credo che i programmatori del "mondo Siemens" dovrebbero farti un monumento, per come approcci i problemi che vengono presentati.

Sei un esempio da seguire...... :clap: :clap:

Link al commento
Condividi su altri siti

Il formato ANY occupa10 byte.

I byte da 4 a 9 sono identici ai byte da 0 a 5 del formato Pointer.

Il byte 0 per S7 contiene sempre 10 Hex

Il byte 1 contiene il tipo di dati (01Hex = Bool; 02Hex = Byte; 03Hex = Char.....)

I byte 2 e 3 contengono quante volte il tipo di dati è ripetuto, cioè la lunghezza dell'area dati.

La stessa funzione poteva essere scritta usando anche il tipo ANY, ma questo avrebbe significato scegliere tra:

1) una funzione più complicata con tanto di analisi del tipo di dato e con istruzioni diversificate a seconda del tipo di dato, oppure calcoli per convertire i diversi tipi di dati possibili sempre nello stesso formato

2) una funzione sostanzialmente uguale a quella già scritta, che obbligava però a passare il parametro in un modo ben preciso, a seconda di come veniva sviluppata la funzione, aumentando le possibilità di errore

Personalmente uso poco il formato ANY. Trovo molto più pratico usare il formato Pointer, più semplice sia da gestire, che come sintassi del parametro da passare.

Per esempio, se alla funzione "BitCnt" voglio far contare i bit a uno da DB5.DBX10.0 a DB5.DBX19.7 al parametro IN posso scrivere:

1) DB5.DBB10

2) DB5.DBX10.0

3) DB5.DBW10

4) DB5.DBD10

5) P#DB5.DBX10.0

e ancora, se il db ha un nome simbolico e l'area è una variabile, un array o una struttura, posso scrivere:

6) "NomeDB".NomeVariabile

7) "NomeDB".NomeArray

8) "NomeDB".NomeStruttura

Il formato Pointer digerisce praticamente tutto.

Con il formato ANY, per non complicare troppo la funzione, avrei dovuto obbligare a scrivere, per esempio:

P#DB5.DBX10.0 WORD 5

Insomma, ritengo il formato Pointer molto più malleabile.

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