Come usare gli operatori per manipolare i bit

Lavorare con i microcontrollori, incluso Arduino, è divenuto abbastanza semplice grazie all’impiego di linguaggi ad alto livello che permettono di imparare in modo semplice e veloce la programmazione di questi device. Nonostante l’uso di funzioni che gestiscono variabili complesse, molte volte si ha la necessità di gestire i singoli bit. Arduino implementa dei metodi per accedere direttamente ai bit di una variabile  e di poterne leggerne e cambiare il valore.

operatori bitwise lavorare con i bit

I bit è l’unità più piccola capace di esprimere un informazione (valori 1 e 0). L’unione di più bit forma altre unità come il byte (composto da 8 bit). Il byte è stato il primo sistema per codificare un carattere ed è capace di esprimere 256 valori (2^8 = 256).
Per accedere ai singoli bit che compongono il byte possiamo usare le funzioni seguenti:

Leggere un singolo bit

Per leggere il valore di un singoli bit usiamo la funzione bitRead(Val, Posizione); dove Val è il valore della variabile e Posizione è il numero del bit da leggere, con indice zero. Eccovi alcuni esempi di utilizzo


byte Data = 0;

void setup()
{
    Serial.begin(9600);
}

void loop()
{
 Data = 0; //in binario 00000000

 Serial.print("Valore in bit della variabile Data(");
 Serial.print(Data);
 Serial.println("):");

 Serial.print(bitRead(Data, 0)); //bit meno significativo
 Serial.print(bitRead(Data, 1));
 Serial.print(bitRead(Data, 2));
 Serial.print(bitRead(Data, 3));
 Serial.print(bitRead(Data, 4));
 Serial.print(bitRead(Data, 5));
 Serial.print(bitRead(Data, 6));
 Serial.print(bitRead(Data, 7)); //bit più significativo
 Serial.println();
 delay(1000);

 Data = 255; //in binario 11111111

 Serial.print("Valore in bit della variabile Data(");
 Serial.print(Data);
 Serial.println("):");

 Serial.print(bitRead(Data, 0)); //bit meno significativo
 Serial.print(bitRead(Data, 1));
 Serial.print(bitRead(Data, 2));
 Serial.print(bitRead(Data, 3));
 Serial.print(bitRead(Data, 4));
 Serial.print(bitRead(Data, 5));
 Serial.print(bitRead(Data, 6));
 Serial.print(bitRead(Data, 7)); //bit più significativo
 Serial.println();
 delay(1000);

 Data = 127; //in binario 11111110

 Serial.print("Valore in bit della variabile Data(");
 Serial.print(Data);
 Serial.println("):");

 Serial.print(bitRead(Data, 0)); //bit meno significativo
 Serial.print(bitRead(Data, 1));
 Serial.print(bitRead(Data, 2));
 Serial.print(bitRead(Data, 3));
 Serial.print(bitRead(Data, 4));
 Serial.print(bitRead(Data, 5));
 Serial.print(bitRead(Data, 6));
 Serial.print(bitRead(Data, 7)); //bit più significativo
 Serial.println();
 delay(1000);
}

Settare un bit

La funzione che permette di mettere a 1 un singolo bit è la seguente bitSet(Val, Posizione); dove Val esprime il valore del byte e Posizione è l’indice del bit da settare.


byte Data = 0;

void setup()
{
 Serial.begin(9600);
}

void loop()
{
 Data = 0; //in binario 00000000

 Serial.print("Valore in bit della variabile Data(");
 Serial.print(Data);
 Serial.println("):");

 Serial.print(bitRead(Data, 0)); //bit meno significativo
 Serial.print(bitRead(Data, 1));
 Serial.print(bitRead(Data, 2));
 Serial.print(bitRead(Data, 3));
 Serial.print(bitRead(Data, 4));
 Serial.print(bitRead(Data, 5));
 Serial.print(bitRead(Data, 6));
 Serial.print(bitRead(Data, 7)); //bit più significativo
 Serial.println();
 delay(2000);

 //setta il bit 0
 bitSet(Data, 0);

 //visualizza il valore di Data
 Serial.print("Valore in bit della variabile Data(");
 Serial.print(Data);
 Serial.println("):");

 Serial.print(bitRead(Data, 0)); //bit meno significativo
 Serial.print(bitRead(Data, 1));
 Serial.print(bitRead(Data, 2));
 Serial.print(bitRead(Data, 3));
 Serial.print(bitRead(Data, 4));
 Serial.print(bitRead(Data, 5));
 Serial.print(bitRead(Data, 6));
 Serial.print(bitRead(Data, 7)); //bit più significativo
 Serial.println();
 delay(2000);

 //setta il bit 7
 bitSet(Data, 7);

 //visualizza il valore di Data
 Serial.print("Valore in bit della variabile Data(");
 Serial.print(Data);
 Serial.println("):");

 Serial.print(bitRead(Data, 0)); //bit meno significativo
 Serial.print(bitRead(Data, 1));
 Serial.print(bitRead(Data, 2));
 Serial.print(bitRead(Data, 3));
 Serial.print(bitRead(Data, 4));
 Serial.print(bitRead(Data, 5));
 Serial.print(bitRead(Data, 6));
 Serial.print(bitRead(Data, 7)); //bit più significativo
 Serial.println();
 delay(2000);
}

Resettare un bit

la funzione che invece permette di mettere a zero un singolo bit è la seguente bitClear(Val, Posizione); dove Val è il solito valore in byte e Posizione rappresenta l’indice del bit da settare a 0.

byte Data = 0;

void setup()
{
 Serial.begin(9600);
}

void loop()
{
 Data = 255; //in binario 11111111

 Serial.print("Valore in bit della variabile Data(");
 Serial.print(Data);
 Serial.println("):");

 Serial.print(bitRead(Data, 0)); //bit meno significativo
 Serial.print(bitRead(Data, 1));
 Serial.print(bitRead(Data, 2));
 Serial.print(bitRead(Data, 3));
 Serial.print(bitRead(Data, 4));
 Serial.print(bitRead(Data, 5));
 Serial.print(bitRead(Data, 6));
 Serial.print(bitRead(Data, 7)); //bit più significativo
 Serial.println();
 delay(2000);

 //resetta il bit 0
 bitClear(Data, 0);

 //visualizza il valore di Data
 Serial.print("Valore in bit della variabile Data(");
 Serial.print(Data);
 Serial.println("):");

 Serial.print(bitRead(Data, 0)); //bit meno significativo
 Serial.print(bitRead(Data, 1));
 Serial.print(bitRead(Data, 2));
 Serial.print(bitRead(Data, 3));
 Serial.print(bitRead(Data, 4));
 Serial.print(bitRead(Data, 5));
 Serial.print(bitRead(Data, 6));
 Serial.print(bitRead(Data, 7)); //bit più significativo
 Serial.println();
 delay(2000);

 //resetta il bit 5
 bitClear(Data, 5);

 //visualizza il valore di Data
 Serial.print("Valore in bit della variabile Data(");
 Serial.print(Data);
 Serial.println("):");

 Serial.print(bitRead(Data, 0)); //bit meno significativo
 Serial.print(bitRead(Data, 1));
 Serial.print(bitRead(Data, 2));
 Serial.print(bitRead(Data, 3));
 Serial.print(bitRead(Data, 4));
 Serial.print(bitRead(Data, 5));
 Serial.print(bitRead(Data, 6));
 Serial.print(bitRead(Data, 7)); //bit più significativo
 Serial.println();
 delay(2000);
}

Settare o resettare con la stessa funzione

Esiste una funzione capace di eseguire sia le operazione di settaggio dei bit sia le operazioni di reset, il suo prototipo è bitWrite(Val, Posizione, ValBit); dove Val è il byte che vogliamo modificare, Posizioe rappresenta l’indice del bit da modificare e ValBit è il valore del bit (1 0 0)

byte Data = 0;

void setup()
{
Serial.begin(9600);
}

void loop()
{
Data = 255; //in binario 11111111

Serial.print("Valore in bit della variabile Data(");
Serial.print(Data);
Serial.println("):");

Serial.print(bitRead(Data, 0)); //bit meno significativo
Serial.print(bitRead(Data, 1));
Serial.print(bitRead(Data, 2));
Serial.print(bitRead(Data, 3));
Serial.print(bitRead(Data, 4));
Serial.print(bitRead(Data, 5));
Serial.print(bitRead(Data, 6));
Serial.print(bitRead(Data, 7)); //bit più significativo
Serial.println();
delay(2000);

//resetta il bit 0
bitWrite(Data, 0, 0);
//resetta il bit 3
bitWrite(Data, 2, 0);

//visualizza il valore di Data
Serial.print("Valore in bit della variabile Data(");
Serial.print(Data);
Serial.println("):");

Serial.print(bitRead(Data, 0)); //bit meno significativo
Serial.print(bitRead(Data, 1));
Serial.print(bitRead(Data, 2));
Serial.print(bitRead(Data, 3));
Serial.print(bitRead(Data, 4));
Serial.print(bitRead(Data, 5));
Serial.print(bitRead(Data, 6));
Serial.print(bitRead(Data, 7)); //bit più significativo
Serial.println();
delay(2000);

//setta il bit 1
bitWrite(Data, 0, 0);
//setta il bit 3
bitWrite(Data, 2, 1);
//resetta il bit 5
bitWrite(Data, 4, 0);

//visualizza il valore di Data
Serial.print("Valore in bit della variabile Data(");
Serial.print(Data);
Serial.println("):");

Serial.print(bitRead(Data, 0)); //bit meno significativo
Serial.print(bitRead(Data, 1));
Serial.print(bitRead(Data, 2));
Serial.print(bitRead(Data, 3));
Serial.print(bitRead(Data, 4));
Serial.print(bitRead(Data, 5));
Serial.print(bitRead(Data, 6));
Serial.print(bitRead(Data, 7)); //bit più significativo
Serial.println();
delay(2000);
}

La funzione bit();

La funzione bit(x); ci permette di calcolare il valore decimale del bit specificato, l’esempio chiarisce meglio il concetto


void setup()
{
Serial.begin(9600);
}

void loop()
{
//valori decimali dei singoli bit
Serial.println(bit(0)); 2^0 = 1
Serial.println(bit(1)); 2^1 = 2
Serial.println(bit(2)); 2^2 = 4
Serial.println(bit(3)); 2^3 = 8
Serial.println(bit(4)); 2^4 = 16
Serial.println(bit(5)); 2^5 = 32
Serial.println(bit(6)); 2^6 = 64
Serial.println(bit(7)); 2^7 = 128

Serial.println();
delay(2000);

}

Negli esempi è stato analizzato il singolo byte ma è possibile lavorare anche con gli altri tipi. Ad esempio possiamo effettuare delle operazioni su una variabile unsigned int (composta da 16 bit (2^16)-1 da 0 a 65535)

unsigned int Data = 65535;

void setup()
{
Serial.begin(9600);
}

void loop()
{

//valore decimale del bit 12
Serial.print("valore decimale del bit 12 ");
Serial.print(bit(12)); // 2^12 = 4096
Serial.println();

Data = 65535;

//visualizza il valore di Data
Serial.print("Valore in bit della variabile Data(");
Serial.print(Data);
Serial.println("):");

Serial.print(bitRead(Data, 0)); //bit meno significativo
Serial.print(bitRead(Data, 1));
Serial.print(bitRead(Data, 2));
Serial.print(bitRead(Data, 3));
Serial.print(bitRead(Data, 4));
Serial.print(bitRead(Data, 5));
Serial.print(bitRead(Data, 6));
Serial.print(bitRead(Data, 7));
Serial.print(bitRead(Data, 8));
Serial.print(bitRead(Data, 9));
Serial.print(bitRead(Data, 10));
Serial.print(bitRead(Data, 11));
Serial.print(bitRead(Data, 12));
Serial.print(bitRead(Data, 13));
Serial.print(bitRead(Data, 14));
Serial.print(bitRead(Data, 15)); //bit più significativo
Serial.println();
delay(2000);

//setta il bit 1
bitWrite(Data, 0, 0);
//resetta il bit 3
bitWrite(Data, 10, 0);
//resetta il bit 5
bitWrite(Data, 15, 0);

//visualizza il valore di Data
Serial.print("Valore in bit della variabile Data(");
Serial.print(Data);
Serial.println("):");

Serial.print(bitRead(Data, 0)); //bit meno significativo
Serial.print(bitRead(Data, 1));
Serial.print(bitRead(Data, 2));
Serial.print(bitRead(Data, 3));
Serial.print(bitRead(Data, 4));
Serial.print(bitRead(Data, 5));
Serial.print(bitRead(Data, 6));
Serial.print(bitRead(Data, 7));
Serial.print(bitRead(Data, 8));
Serial.print(bitRead(Data, 9));
Serial.print(bitRead(Data, 10));
Serial.print(bitRead(Data, 11));
Serial.print(bitRead(Data, 12));
Serial.print(bitRead(Data, 13));
Serial.print(bitRead(Data, 14));
Serial.print(bitRead(Data, 15)); //bit più significativo
Serial.println();
delay(2000);

}

Manipolare i bit sembra macchinoso ma il vantaggio è che Arduino esegue molto velocemente questo tipo di operazioni, vedremmo successivamente come sia possibile eseguire semplici operazioni lavorando con i singoli bit.

[facebook_ilike]