Você está na página 1de 9

Bits em Linguagem C - Conceito e Aplicao

Fonte: http://www.embarcados.com.br/bits-em-linguagem-c/

O domnio de operaes com bits essencial quando se est trabalhando em programao de


microcontroladores. Sempre ser necessrio usar bits para a configurao de registradores,
configurao de funes especficas e tambm para leitura de status para tomada de deciso.
Quando se trabalha com a linguagem Assembly essas operaes so mais naturais, j que existem
operaes diretas para isso. Por outro lado a linguagem C tambm trs a facilidade de acesso aos
registradores e manipulao de bits atravs dos operadores lgicos bit a bit. Neste artigo iremos
abordar o uso de bits em Linguagem C e as principais operaes lgicas em linguagem C.

Operaes lgicas para usar bits em Linguagem C


Antes de conhecer os operadores binrios da Linguagem C, vamos relembrar as operaes lgicas em
sistemas digitais. Thiago Lima apresentou um excelente resumo sobre portas lgicas e vamos usar o
seu artigo como referncia.
Lgica No (NOT)
Inverte o estado do bit.
Tabela verdade:

Lgica E (AND)
A sada ser igual a 1 somente se todos os bits de entrada forem iguais a 1. Se pelo menos um dos
bits for 0, a sada ser 0.
Tabela verdade:

Lgica OU (OR)
A sada assumir nvel lgico 1 se pelo menos 1 bit de entrada for igual a 1. Somente assumir nvel
lgico 0 se todas as entradas apresentarem nvel lgico 0.
Tabela verdade:

Lgica Ou-Exclusivo (XOR)


A sada ser igual a 0 se as entradas forem iguais. Caso as entradas forem diferentes a sada assumir
o valor 1.
Tabela verdade:

Operadores binrios em linguagem C


A linguagem C apresenta uma grande variedade de operadores. A seguir so apresentados os
operadores para operaes binarias, bit a bit:
Operador

Funo

&

E (AND)

OU (OR)

OU-EXCLUSIVO (XOR)

NOT ou Complemento de 1

<<

Deslocamento esquerda

>>

Deslocamento direita

Os operadores &, |, ^ e ~ funcionam como apresentado anteriormente e tm as saidas conforme


exibidos em suas tabelas verdades. Os operadores de deslocamento fazem o shift de bits para
esquerda ou direita.
Exemplo:
Vamos assumir que x incialmente tenha o valor 0b00000001, valor 1 em decimal.
x = (x<<2);

Aps a operao acima, ser atribuido a x o valor 0b000000100, valor 4 em decimal.


Se em seguida realizarmos uma operao de deslocamento direita:
x = (x>>1);

Aps essa operao ser atribudo varivel x o valor 0b00000010, valor 2 em decimal.
Note que a operao de deslocamento esquerda multiplica por dois a cada shift. J o deslocamento
direita, divide por dois a cada shift. Dessa forma pode-se tambm utilizar esses operadores para
multiplicao ou diviso por 2, sendo mais eficiente que utilizando o operador de multiplicao.

Usando mscara de bits


Para manipulao dos bits utilizam-se mscaras de bits que possibilitam a alterao ou leitura de bits
especficos sem a alterao de outros. A seguir so exibidas algumas operaes.
Ativando um bit
Para ativar um bit especifico de uma varivel ou registrador, ou seja, colocar nvel lgico 1, utiliza-se
o operador |(OU). Por exemplo, desejamos colocar em nivel 1 o bit 5 do PORTB, no ATmega328. Para
isso fazemos a seguinte operao:
PORTB = PORTB|0b00100000;

XXXXXXXX
|00100000
XX1XXXXX

-> valor presente no registrador PORTB


-> mscara para alterao do bit 5
-> resultado, apenas o bit 5 alterado

Para facilidade na criao da mscara, utiliza-se o operador de deslocamento esquerda, ficando da


seguinte forma:
PORTB = PORTB | (1<<5);

Ser feita a lgica OU com o byte criado na operao (1<<5), que deslocou o valor '1' 5 vezes para a
esquerda.
A operao pode ser simplificada, ficando da seguinte forma:
PORTB |= (1<<5);

Limpando um bit
Para limpar um bit especfico de uma varivel ou registrador, ou seja, colocar nvel lgico 0, utiliza-se
o operador & (AND). Vamos utilizar o mesmo registrador e bit utilizado no exemplo anterior como
exemplo:
PORTB = PORTB & 0b11011111;

XXXXXXXX

-> valor presente no registrador PORTB

&11011111

-> mscara para alterao do bit 5

XX0XXXXX

-> resultado, apenas o bit 5 alterado

Usando o operador de deslocamento ficar da seguinte forma:


PORTB = PORTB & (~(1<<5);

Note que necessrio inverter os valores para a mscara ficar da forma desejada.
A operao pode ser simplificada, ficando da seguinte forma:
PORTB &= ~(1<<5);

Invertendo o estado de um bit


Para inverter o estado lgico de um bit utiliza-se o operador ^ (OU-Exclusivo). Continuamos com o
mesmo bit e registrador dos exemplos anteriores:
PORTB = PORTB^0b00100000;

XX1XXXXX
^00100000
XX0XXXXX

-> valor presente no registrador PORTB


-> mscara para alterao do bit 5
-> resultado, o bit 5 invertido

Usando o operador de deslocamento ficar da seguinte forma:


PORTB = PORTB ^ (1<<5);

A operao pode ser simplificada, ficando da seguinte forma:


PORTB ^= (1<<5);

Testando valor de um bit


Para teste de um bit tambm utilizaremos a lgica & (AND) para operao com a mscara de bits. Por
exemplo, temos uma tecla ligada ao pino 2 do PORTD do Atmega328. Para leitura desse pino
utilizamos o registrador PIND. A operao ficar da seguinte forma:
PIND & (1<<4)

XXXXXTXX
&00000100
00000T00

-> valor presente no registrador PIND


-> mscara para alterao do bit 2
-> resultado, o valor do bit estar presente no resultado

Caso o bit de teste tenha o valor 1, o resultado conter o valor 1 somente na posio do bit, caso
contrrio o resultado ser 0.
Esta operao pode ser usada em uma estrutura de descio if, por exemplo:
if (PIND & (1 << 4)) {
//executa comandos dentro do if se o pino testado estiver com o valor lgico 1
}

Criando Macros
Fernando Deluno Garcia apresentou uma excelente srie sobre o Pr-Processador C. Utilizando seus
atigos como referncia, vamos criar algumas macros para manipulao de bits utilizando as
operaes apresentadas.

set bit

#define setBit(valor,bit) (valor |= (1<<bit))

clear bit

#define clearBit(valor,bit) (valor &= ~(1<<bit))

toogle bit

#define toogleBit(valor,bit) (valor ^= (1<<bit))

teste bit

#define testBit(valor,bit)

(valor & (1<<bit))

Exemplo de aplicao
O exemplo a seguir exibe o uso das macros apresentadas para manipulao de bits no Atmega328P.
Foi utilizada a IDE Arduino, para que voc possa facilmente testar, utilizando a placa Arduino UNO.
#define
#define
#define
#define

setBit(valor,bit)
(valor |= (1<<bit))
clearBit(valor,bit)
(valor &= ~(1<<bit))
testBit(valor,bit)
(valor & (1<<bit))
toggleBit(valor, bit) (valor ^= (1<<bit))

#define LED 5
#define BT 2
void setup() {
setBit(DDRB,LED);
clearBit(DDRD,BT);

//pino PB5 para o LED


//pino PD2 para o BT
//configura pino PB5 como sada
//configura pino PD2 como entrada

}
void loop() {
if(!testBit(PIND,BT)){
setBit(PORTB,LED);
}
else{
clearBit(PORTB,LED);
}
}

//se boto pressionado


//liga led
//se no
//apaga led

Podemos tambm usar a compilao condicional, conforme apresentada no artigo Pr-processador


C: Compilao condicional, escrito por Fernando Deluno Garcia, e testar o tamanho de cdigo gerado,
usando macros e as funes do Arduino:
//#define ARDUINO_FUNC 1 //comente para uso de macros
#define setBit(valor,bit)
(valor |= (1<<bit))
#define clearBit(valor,bit)
(valor &= ~(1<<bit))
#define testBit(valor,bit)
(valor & (1<<bit))
#define toggleBit(valor, bit) (valor ^= (1<<bit))
#ifdef ARDUINO_FUNC
#define LED 13
#define BT 2

//pino 13 para o LED


//pino 2 para o BT

#else
#define LED 5

//pino PB5 para o LED

#define BT
#endif

//pino PD2 para o BT

void setup() {
#ifndef ARDUINO_FUNC
setBit(DDRB,LED);
clearBit(DDRD,BT);

//configura pino PB5 como sada


//configura pino PD2 como entrada

#else
pinMode(LED, OUTPUT);
pinMode(BT, INPUT);
#endif }
void loop() {
while(1){
toggleBit(PORTB,LED);
delay(1000);
}
#ifndef ARDUINO_FUNC
if(!testBit(PIND,BT)){
setBit(PORTB,LED);
}
else{
clearBit(PORTB,LED);

//se boto pressionado


//liga led
//se no
//apaga led

}
#else
if(digitalRead(BT) == LOW){
digitalWrite(LED,HIGH);
}
else{

digitalWrite(LED,LOW);
}
#endif
}

Compile nas duas condies e verifique o tamanho do cdigo gerado em cada uma delas. Note que o
cdigo gerado utilizando macros bem menor do que quando utilizando as funes Arduino.
As macros utilizadas acimas podem ser aplicadas em diversas plataformas e facilitam em operaes
com bits.