sostituire un singolo bit in una variabile byte

ciao a tutti...

mi trovo alle prese con l'esigenza di dover sostituire alcuni bit (uno o più di uno) in un variabile byte così fatta:

variabile = B00110010

prima di passarla ad una funzione ho l'esigenza, a seconda dei casi, di modificare 1 o più bit...

non ho ancora provato, ma stasera provo con bitWrite()...
intanto volevo chiede .. esiste qualche metodo, sistema, per cambiare in blocco alcuni bit, con funzioni tipo bitwise etc...

grazie

Il modo più semplice per chi non ha esperienza di manipolazione dei bit (come immagino, vista la domanda... :sweat_smile:) è di usare le funzioni predefinite di Arduino, che sono semplici e funzionali.

bitSet(variabile, bit) modifica a 1 il bit in posizione "bit" della variabile "variabile"
bitClear(variabile, bit) come sopra ma imposta il bit a 0
bitRead(variabile, bit) per leggere il valore del bit indicato

Ricordati che le posizioni dei bit partono da 0 ed arrivano a 7 (totale 8 posizioni), partendo da destra verso sinistra. Quindi il bit n° 0 è il bit più a destra (meno significativo)

Grazie Leo...
in effetti sto studiando .... e quella tecnica credo di aver capito come usarla ... anzi la sto già usando ....

ma, mi chiedevo, con la tecnica di manipolazione dei bit... come si può fare a sostituire , magari con una sola istruzione, solo alcuni bit in un byte .....

Un byte è composto da 8 bit.
Un numero puoi passarlo ad Arduino nella sua rappresentazione decimale o binaria, a lui non cambia.
Quindi 128 = 0b10000000
Il primo è il numero come siamo abituati a vederlo noi, il secondo come in realtà lo memorizza l'MCU nella memoria.
Da DX a SX il peso dei bit aumenta ed ognuno viene poi usato per riconvertirlo in decimale con la classica formuletta
bit0(20) + bit1(21)+....bit7(27)
Riprendendo l'esempio 0b10000000 hai solo da fat bit7
(27) (perché tutti gli altri bit sono a 0) ed ottieni 1*128 = 128.

Detto questo per capire un po' le cose, mettiamo che vuoi ACCENDERE, cioè impostare ad 1 un bit. Si usa l'operazione OR sui bit. OR restituisce 1 quando anche 1 solo dei 2 bit da confrontare è ad 1.
Quindi volendo ad esempio accendere il bit in 7a posizione, fai:
0b10000000 OR 0b01000000 = 0b11000000
Traducendo in C hai: 128 | 64 = 192
Il segno "|" è l'operazionale OR in codice C.
Se tu ora vuoi invece spengere, cioè impostare a 0, un bit fai semplicemente l'AND tra 2 bit. Che restituisce 0 anche se uno solo dei 2 bit è a 0, per cui 1 AND 0 sei sicuro che dia 0. Riprendiamo l'esempio di sopra e spengiamo il bit in 8a posizione:
0b11000000 AND 0b01111111 = 0b01000000
In C hai: 192 & 127 = 64
Perché? Perché tu hai messo uno 0 sul bit più significativo ed una serie di 1 sugli altri. Quindi hai detto di mantenere il valore dei bit 0..6 e di spengere il bit in ultima posizione.

Per capire le operazioni con l'algebra di Boole usa anche questa pagina:

PS:
ci sarebbe un altro metodo. Alle volte vedi ad esempio una notazione tipo questa: var |= (1<<5)
Ti accenno solo che usa lo spostamento dei bit (bit shift) ma è un pochino più avanzata, per ora capisci la precedente.

Grazie...
grazie leo.. per quanto riguarda la trsformazione binario - decimale non cè problema. Ho studiato un pò di fortran 25 anni orsono... (non sono più giovanissimo) ....
quindi ricapitolando:
mi pare di aver capito che per 'accendere' alcuni bit devo fare l'OR con una maschera, per esempio, se voglio impostare i bit in posizione 1 e 2 (secondo e terzo) , sulla variabile val = B01010001 faccio

val = val | B00000110 ed ottengo B01010111 ... quindi ho impostato ad 1 i bit in posizoine 1 e 2....

se voglio impostare i bit in posizione 4 e 5 (quinto e sesto) a 0, faccio l'AND così:

val = val & B10011111 ed ottengo B01000001

credo di aver capito.. ed era esattamente ciò che cercavo ....
grazie ... per l'altro metodo invece dove trovo qualche riferimento in rete???
grazie...

Questo non mi torna. Da dove l'hai tirato fuori B01000001?
Se val ha il valore iniziale, B01010001,
val = val & B10011111 da come risultato 0b00010001
perché
1 & 0 = 0
0 & 1 = 0

val B01010001
and B10011111
= B01000001 sbagliato .. ok

val B01010001
and B10011111
= B00010001 giusto .. ok

avevo sbagliato io facendo ad "occhio" ... comunque lo sto già usando e mi ha alleggerito moltissimo il codice. mi sembra che funzioni tutto ok.... credo non ci siano "bachi" ...

senti .. tu indichi il valore con notazione binaria così "ob00000000" .... ma che differenza c'è nello scrivere "0b00000000" oppure "B00000000" .... o meglio : è preferibile usare la tua notazione alla mia o è indifferente?

e sull'altro metodo che mi hai indicato? .. con il bit shift???

sto già usando questo metodo per estrarre delle informazioni da un variabile byte:

dtmf_codice = (PIND & B11110000)>>4; // legge i 4 bit (da 4 a 7) della porta D effetua il bitwise AND con 11110000 e shifta a destra di 4 (estrae un valore tra 0 e 15)

per estrarre alcuni bit da una variabile byte .... probabilmente lo posso usare anche per 'mettere' alcuni bit in una variabile byte in un'unica operazione...

Io scrivo 0b per i binari, ox per gli esadecimali. E' una questione di abitudine.
Gli shift sono un modo veloce per spostare i valori all'interno di una variabile.

Se il bit meno significativo è 1, spostandolo a SX di n posizioni ottieni lo stesso risultato che accendere il bit finale con un OR.