Olá pessoal!
Nesse novo artigo usaremos matemática com BITS, operadores lógicos e outros conceitos interessantes para manipular números inteiros.
Os números e a matemática dominam nossa vida. Não passamos um dia sem usarmos uma álgebra ou um calculo mesmo que não seja diretamente. O que não nos mostram na escola é que os números podem ter diferentes representações e só nos é apresentada o sistema de base dez ou decimal.
No mundo das maquinas aonde os números são representados em conjuntos de 1 e 0 temos a base dois ou binária que será usada no dia a dia de um programador de sistemas embarcados.Bem como a hexadecimal aonde temos um sistema de base 16 que nos ajudara a representar números binários longos.
Os números no sistema binário serão representados com sequências de 1 e 0 porem como trabalhar esses valores?
Que numero decimal o binário 10010010 representa?
A conversão se dará assim:
casa: 7 6 5 4 3 2 1 0
numero: 1 0 0 1 0 0 1 0
2^Casa:128 64 32 16 8 4 2 1 = 128+16+2=146.
A conversão se trata basicamente de multiplicar o binário da referida casa por uma potencia de 2 elevado a casa do numero. O maior numero decimal a ser representado por um numero de 8Bits seria 255 então podemos usar em um registrador um inteiro de 0 a 255.
Seguindo essa linha de raciocínio qual seria o maior numero representando por um inteiro de 16 bits?
Operadores lógicos
Para quem nunca fez um curso voltado a área de tecnologia fica complicado entender a lógica por trás de varias ferramentas implementadas em compiladores.
Temos basicamente quatro operadores lógicos no C:
OR representado pelo “|”
AND representado pelo “&”
XOR representado pelo “^”
NOT representado pelo “~”
Cada operador possui uma tabela verdade que mostra o seu comportamento:
Bitwise OR (OU)(|):
0 | 0 == 0
0 | 1 == 1
1 | 0 == 1
1 | 1 == 1
Como observamos o comportamento desse operador se trata quando “uma entrada ou outra” estão em 1 a saída será um.
Exemplo usando 8bits: 0b10001000|0b0110001 =?
0b10001000
0b01100001 =0b11101001
A lógica OR servira para certificar que um certo bit em um numero será 1.
Bitwise AND (e)(&):
0 & 0 == 0
0 & 1 == 0
1 & 0 == 0
1 & 1 == 1
Como observamos o comportamento desse operador se trata quando “uma entrada e a outra” estão em 1 a saída será um.
Exemplo usando 8bits: 0b10001001&0b0110001 =?
0b10001001
&
0b01100001 = 0b00000001
A lógica AND servira para verificar qual o estado de um bit em certa casa decimal.
Por exemplo:
Ob11001100 & 0b00001000 == 1
ou
Ob11001100 & 0b00000001 == 0
Bitwise NOT (não)(~):
~ 0 == 1
~ 1 == 0
Como observamos o operador NOT inverte o valor de entrada.
Exemplo usando 8bits: ~0b10001001 == 0b01110110
A logica NOT poderá ser usada para inverter o estado de um numero ou mesmo mudar o comportamento de operadores lógicos anteriores como o OR ou AND.
Bitwise XOR (OU EXCLUSIVA)(^):
0 ^ 0 == 0
0 ^ 1 == 1
1 ^ 0 == 1
1 ^ 1 == 0
Verificamos que a saída do operador será “1” quando as entradas forem diferentes ou exclusivamente um ou outro
Exemplo usando 8bits: 0b10000001^0b00000001 =?
0b10000001
^
0b00000001 = 0b10000000
Pois:
casa 7: 1^0==1
casa 6: 0^0==0
casa 5: 0^0==0
casa 4: 0^0==0
casa 3: 0^0==0
casa 2: 0^0==0
casa 1: 0^0==0
casa 0: 1^0==0
A lógica XOR servira para inverter o estado de um determinado BIT por exemplo.
BIT SHIFT
Podemos alterar a posição de um bit usando os operadores de deslocamento.
>>
: para deslocar a direita
<<
: para deslocar a esquerda
exemplo:
0b00010000<<3==0b10000000
0b00010000>>7==0b00000001
Mas finalmente amigo para que serve tudo isso.
Irei dar exemplos simples:
Como veremos em um futuro artigo cada pino de GPIO corresponde a um BIT de um endereço de memoria. O PORTD seria o nome do endereço com os 8bits referentes aos 8 pinos do mesmo.
1: Queremos acionar uma luz no pino 4 do PORTD porem não podemos alterar nenhum outro BIT no mesmo PORT pois no pino 3 temos uma sirene e no 2 o controle de uma tranca.Destacando que o primeiro BIT é representado por 0 e o 8º sera o numero 7.
O estado atual do PORTD esta assim: 0b00000100
Como vimos o pino 2 é a tranca e esta acionada não posso em uma operação desativar essa tranca.
Se eu fizer somente isso PORTD=Ob00010000;
teremos um erro catastrofico pois iremos limpar o BIT referente a tranca.
Para um correto acionamento usaremos a lógica OR: PORTD=PORTD|0b0001000
Como o estado do PORTD era: 0b00000100
0b00000100
|
0b00010000 == 0b00010100
Sucesso!!! Acionaremos nossa lampada sem desativar nossa tranca
Podemos simplificar a expressão ainda assim: PORTD|=0b0001000
ou ainda usando bit shift com a seguinte expressão PORTD|=(1<<4)
Passado algum tempo queremos que a luz seja desactivada porem como no caso anterior sem mexer nos outros BITS.
Não da para usar a lógica OR pois 1|0
ira retornar “1” não fazendo diferença. Usando uma lógica AND temos o resultado esperado pois 1&0==0
e para manter os outros BITS podemos fazer uma AND com 1 pois 1&1==1
e 0&1==0
então todo BIT que estiver em 1 continuara bem como 0 continuara 0.
0b00010100
&
0b11101111 = 0b00000100
então obtemos a expressão PORTD=PORTD&0b11101111;
seguindo a mesma lógica da lógica OR podemos reduzir a expressão PORTD&=&0b11101111;
.
Podemos usar o bitshift nesse caso porem com a seguinte lógica:
(1<<4)==0b00010000
~0b00010000==0b11101111
Realizaremos então um deslocamento a esquerda e apos uma inversão resultando na expressão:
PORTD&=~(1<<4);
ótimo agora podemos setar e apagar bits sem alterar outros em um endereço de memoria.
Pessoal por hoje é só.Ate a proxima!