Bits em Linguagem C – Conceito e Aplicação

bits

O domínio de operações com bits é essencial quando se está trabalhando em programação de microcontroladores. Sempre será necessário usar bits para a configuração de registradores, configuração de funções específicas e também para leitura de status para tomada de decisão. Quando se trabalha com a linguagem Assembly essas operações são mais naturais, já que existem operações diretas para isso. Por outro lado a linguagem C também trás a facilidade de acesso aos registradores e manipulação de bits através dos operadores lógicos bit a bit. Neste artigo iremos abordar o uso de bits em Linguagem C e as principais operações lógicas em linguagem C.

Operações lógicas para usar bits em Linguagem C

Antes de conhecer os operadores binários da Linguagem C, vamos relembrar as operações lógicas em sistemas digitais. Thiago Lima apresentou um excelente resumo sobre portas lógicas e vamos usar o seu artigo como referência.

Lógica Não (NOT)

Inverte o estado do bit.

Tabela verdade:

bits-not

Lógica E (AND)

A saída será igual a 1 somente se todos os bits de entrada forem iguais a 1. Se pelo menos um dos bits for 0, a saída será 0.

Tabela verdade:

bits-and

Lógica OU (OR)

A saída assumirá nível lógico 1 se pelo menos 1 bit de entrada for igual a 1. Somente assumirá nível lógico 0 se todas as entradas apresentarem nível lógico 0.

Tabela verdade:

bits-or

Lógica Ou-Exclusivo (XOR)

A saída será igual a 0 se as entradas forem iguais. Caso as entradas forem diferentes a saída assumirá o valor 1.

Tabela verdade:

bits-XOR

Operadores binários em linguagem C

A linguagem C apresenta uma grande variedade de operadores. A seguir são apresentados os operadores para operações binarias, bit a bit:

Operador

Função

&

E (AND)

|

OU (OR)

^

OU-EXCLUSIVO (XOR)

~

NOT ou Complemento de 1

<<

Deslocamento à esquerda

>>

Deslocamento à direita

Os operadores &, |, ^ e ~ funcionam como apresentado anteriormente e têm 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.

Após a operação acima,  será atribuido a x o valor 0b000000100, valor 4 em decimal.

Se em seguida realizarmos uma operação de deslocamento à direita:

Após essa operação será atribuído à variável x o valor 0b00000010, valor 2 em decimal.

Note que a operação de deslocamento à esquerda multiplica por dois a cada shift. Já o deslocamento à direita, divide por dois a cada shift. Dessa forma pode-se também utilizar esses operadores para multiplicação ou divisão por 2, sendo mais eficiente que utilizando o operador de multiplicação.

Usando máscara de bits

Para manipulação dos bits utilizam-se máscaras de bits que possibilitam a alteração ou leitura de bits específicos sem a alteração de outros. A seguir são exibidas algumas operações.

Ativando um bit

Para ativar um bit especifico de uma variável ou registrador, ou seja, colocar nível lógico 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 operação:

 

X

X

X

X

X

X

X

X

                      -> valor presente no registrador PORTB

|

0

0

1

0

0

0

0

0

                       -> máscara para alteração do bit 5
 

X

X

1

X

X

X

X

X

                        -> resultado, apenas o bit 5 é alterado

Para facilidade na criação da máscara, utiliza-se o operador de deslocamento à esquerda, ficando da seguinte forma:

Será feita a lógica OU com o byte criado na operação (1<<5), que deslocou o valor ‘1’ 5 vezes para a esquerda.

A operação pode ser simplificada, ficando da seguinte forma:

Limpando um bit

Para limpar um bit específico de uma variável ou registrador, ou seja, colocar nível lógico 0, utiliza-se o operador & (AND). Vamos utilizar o mesmo registrador e bit utilizado no exemplo anterior como exemplo:

 

X

X

X

X

X

X

X

X

                                 -> valor presente no registrador PORTB

&

1

1

0

1

1

1

1

1

                                 -> máscara para alteração do bit 5
 

X

X

0

X

X

X

X

X

                                 -> resultado, apenas o bit 5 é alterado

Usando o operador de deslocamento ficará da seguinte forma:

Note que é necessário inverter os valores para a máscara ficar da forma desejada.

A operação pode ser simplificada, ficando da seguinte forma:

Invertendo o estado de um bit

Para inverter o estado lógico de um bit utiliza-se o operador ^ (OU-Exclusivo). Continuamos com o mesmo bit e registrador dos exemplos anteriores:

 

X

X

1

X

X

X

X

X

                            -> valor presente no registrador PORTB

^

0

0

1

0

0

0

0

0

                            -> máscara para alteração do bit 5
 

X

X

0

X

X

X

X

X

                            -> resultado, o bit 5 é invertido

Usando o operador de deslocamento ficará da seguinte forma:

A operação pode ser simplificada, ficando da seguinte forma:

Testando valor de um bit

Para teste de um bit também utilizaremos a lógica & (AND) para operação com a máscara de bits. Por exemplo, temos uma tecla ligada ao pino 2 do PORTD do Atmega328. Para leitura desse pino utilizamos o registrador PIND. A operação ficará da seguinte forma:

 

X

X

X

X

X

T

X

X

                                -> valor presente no registrador PIND

&

0

0

0

0

0

1

0

0

                                -> máscara para alteração do bit 2
 

0

0

0

0

0

T

0

0

                                 -> 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 posição do bit, caso contrário o resultado será 0.

Esta operação pode ser usada em uma estrutura de descição if, por exemplo:

Criando Macros

Fernando Deluno Garcia apresentou uma excelente série sobre o Pré-Processador C. Utilizando seus atigos como referência, vamos criar algumas macros para manipulação de bits utilizando as operações apresentadas.

  • set bit
  • clear bit
  • toogle bit
  • teste bit

Exemplo de aplicação

O exemplo a seguir exibe o uso das macros apresentadas para manipulação de bits no Atmega328P. Foi utilizada a IDE Arduino, para que você possa facilmente testar, utilizando a placa Arduino UNO.

Podemos também usar a compilação condicional, conforme apresentada no artigo Pré-processador C: Compilação condicional, escrito por Fernando Deluno Garcia, e testar o tamanho de código gerado, usando macros e as funções do Arduino:

Compile nas duas condições e verifique o tamanho do código gerado em cada uma delas. Note que o código gerado utilizando macros é bem menor do que quando utilizando as funções Arduino.

As macros utilizadas acimas podem ser aplicadas em diversas plataformas e facilitam em operações com bits.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Comentários:
Notificações
Notificar
guest
10 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Ivanizio Ramalho
Ivanizio Ramalho
02/10/2015 09:41

Olá Fábio, uma didática excelente, parabéns!

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
Reply to  Ivanizio Ramalho
02/10/2015 09:59

Muito obrigado Ivanizio. Muito bom ler isso!

Se tiver alguma sugestão para artigos, deixe comentário.

Abraços

Rafael Dias
Rafael Dias
01/10/2015 13:38

outro ponto interessante também é a utilização de bit-fields para a realização destas operações de manipulação de bits. É uma operação que, dependendo do compilador e da arquitetura, pode deixar a desejar se comparado a manipulação dos bits através de máscaras e operações de deslocamento.

Muito legal o seu artigo, Fabio. Parabéns!

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
Reply to  Rafael Dias
01/10/2015 14:10

ótima observação Rafael, realmente são muito utilizados.

Valeu.

Humberto Trindade da Silva
Humberto Trindade
29/09/2015 09:33

Excelente artigo!! Parabéns!

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
Reply to  Humberto Trindade
29/09/2015 10:54

Olá Humberto, muito obrigado!
Abraços

Pedro Henrique Bertoleti
phfbertoleti
29/09/2015 09:13

Muito bom!

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
Reply to  phfbertoleti
29/09/2015 10:54

Valeu Pedrão. Abraços

Rui Conti
Rui Conti
28/12/2016 19:39

Ótimo artigo, Fábio. Apenas apontando uma correção: na parte onde você explica a leitura dos bits, fala-se no texto da leitura do 2º bit mas no código lê-se o 4º. No mais, parabéns!

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
Reply to  Rui Conti
02/01/2017 13:08

Olá Rui, muito obrigado pela correção. Abraços

Talvez você goste:

Séries

Menu

EVENTO ONLINE

Simplificando seus projetos de Internet das coisas com o iMCP HT32SX Sigfox

DATA: 18/05 às 15:00h