Fundamentos · 20 min de leitura

Portas lógicas explicadas: tabelas-verdade de AND, OR, NOT e XOR e Arduino

O que são portas lógicas? Símbolos de AND, OR, NOT, NAND, NOR, XOR e XNOR, tabelas-verdade, chips 74HC08 e 74HC00, um meio somador e código para Arduino, ESP32 e Pico.

As portas lógicas são os blocos básicos dos circuitos digitais: cada uma olha uma ou mais entradas digitais e gera uma única saída digital segundo uma regra fixa. As entradas só podem ser 0 (LOW) ou 1 (HIGH), e a saída também. Existem sete portas básicas: AND, OR, NOT, NAND, NOR, XOR e XNOR. Do processador do seu celular à placa de controle de uma máquina de lavar, do ATmega328P dentro de um Arduino a uma calculadora de bolso, todo aparelho digital funciona combinando milhões de pequenas portas lógicas.

Neste guia você vai aprender o símbolo e a tabela-verdade de cada porta, chips reais como o 74HC08, o 74HC32 e o 74HC00, um experimento na protoboard montado com dois botões, como montar todas as outras portas só com NAND e o circuito meio somador, que soma dois bits. Nas últimas seções, transformamos a mesma lógica em código no Arduino com os operadores &&, || e ! e com operações bit a bit e depois seguimos com exemplos para ESP32 e Raspberry Pi Pico (MicroPython).

Protoboard para experimentos com portas lógicas
Você pode testar chips de portas lógicas sem solda encaixando-os atravessados no canal do meio de uma protoboard.

O que é uma porta lógica e como ela funciona?

Na eletrônica digital, todo sinal está em um de dois estados: 1 (HIGH, verdadeiro) ou 0 (LOW, falso). A matemática que trabalha com esses dois valores se chama álgebra booleana; em um livro publicado em 1854, George Boole expressou o raciocínio lógico como álgebra exatamente dessa forma. Em 1937, Claude Shannon mostrou que essa álgebra corresponde um a um aos circuitos de chaveamento feitos com relés, criando a base do projeto de circuitos digitais. Hoje uma porta lógica tem só alguns transistores: na tecnologia CMOS, uma porta NOT é feita de 2 MOSFETs e uma NAND de 4. Explicamos como um transistor funciona como chave em O que é um transistor?.

Então, que tensão um circuito chama de 1 e qual chama de 0? Isso depende da tensão de alimentação da placa e da família do chip. A tabela abaixo mostra os limites em que uma entrada é garantidamente entendida como 1 ou como 0. A região entre os dois limites é a região indefinida; se uma entrada ficar ali, a saída pode se comportar de forma aleatória. Uma entrada que não está ligada a nada, uma entrada flutuante, fica vagando justamente nessa região indefinida. Por isso toda entrada precisa estar ligada a um sinal ou, através de um resistor, ao GND ou ao VCC.

Placa / famíliaAlimentaçãoEntrada garantida como 1Entrada garantida como 0
Arduino Uno (ATmega328P)5 V≥ 3,0 V≤ 1,5 V
ESP323,3 V≥ 2,5 V≤ 0,8 V
Raspberry Pi Pico (RP2040)3,3 V≥ 2,0 V≤ 0,8 V
Chip 74HC5 V≥ 3,5 V≤ 1,5 V
Chip 74HCT5 V≥ 2,0 V≤ 0,8 V
Chip CD40005 V≥ 3,5 V≤ 1,5 V

As 7 portas lógicas básicas e seus símbolos

Os esquemas desenham as portas seguindo dois padrões diferentes. No padrão americano (ANSI/IEEE), cada porta tem o seu próprio formato: a AND parece a letra D, a OR um escudo pontudo e a NOT um triângulo. O pequeno círculo (bolinha) na saída significa “inverter”; uma NAND é na verdade uma AND com uma bolinha na ponta. O que distingue a XOR da OR é a segunda linha curva do lado das entradas. No padrão europeu (IEC), todas as portas são retângulos, diferenciados pela marca escrita dentro: & para AND, ≥1 para OR, =1 para XOR e 1 para NOT. Nos livros didáticos você também vai ver NAND escrita como NÃO-E, NOR como NÃO-OU, XOR como OU exclusivo e XNOR como NOR exclusivo.

PortaTambém chamada deSímbolo ANSIMarca IECExpressão booleanaQuando a saída é 1?
ANDConjunção (E)Formato de D&Y = A · BAs duas entradas são 1
ORDisjunção (OU)Escudo pontudo≥1Y = A + BPelo menos uma entrada é 1
NOTInversor (NÃO)Triângulo + bolinha1 (bolinha na saída)Y = A'A entrada é 0
NANDNÃO-EFormato de D + bolinha& (bolinha na saída)Y = (A · B)'Pelo menos uma entrada é 0
NORNÃO-OUEscudo + bolinha≥1 (bolinha na saída)Y = (A + B)'As duas entradas são 0
XOROU exclusivoEscudo com curva dupla=1Y = A ⊕ BAs entradas são diferentes
XNORNOR exclusivoCurva dupla + bolinha=1 (bolinha na saída)Y = (A ⊕ B)'As entradas são iguais

Tabelas-verdade das portas lógicas

Uma tabela-verdade lista a saída que uma porta dá para cada combinação das suas entradas. Uma porta com n entradas tem 2ⁿ linhas: 4 linhas para duas entradas, 8 para três e 16 para quatro. Se você escrever as linhas na ordem da contagem binária (00, 01, 10, 11), nunca pula uma combinação. Aqui estão as seis portas de duas entradas em uma única tabela:

ABANDORNANDNORXORXNOR
00001101
01011010
10011010
11110001

Como a porta NOT tem uma única entrada, a tabela dela tem duas linhas: quando A = 0 a saída é 1, e quando A = 1 a saída é 0. Olhe a tabela com atenção e você vai ver um padrão: a coluna NAND é exatamente o oposto da AND, a NOR o oposto da OR e a XNOR o oposto da XOR. Para memorizar, use estas regras curtas: a AND pergunta “são todas 1?”, a OR pergunta “pelo menos uma é 1?”, a XOR pergunta “as entradas são diferentes?”; uma porta cujo nome começa com N dá a resposta oposta à mesma pergunta. Para testar as portas você mesmo e ver os símbolos ao vivo, basta tocar nas entradas A e B da ferramenta Portas lógicas.

  • AND: duas chaves em série. A lâmpada só acende quando as duas chaves estão fechadas; um cofre de banco que abre com duas chaves diferentes também segue a regra AND.
  • OR: dois botões em paralelo. A mesma campainha toca quer alguém aperte o botão da porta da frente, quer o da porta dos fundos.
  • NOT: a luz da geladeira. Com a porta fechada, a chave fica pressionada e a lâmpada apagada; quando a porta abre, a chave é solta e a lâmpada acende.
  • NAND: a regra “avise, a não ser que esteja tudo certo”. Se mesmo uma das duas proteções de segurança de uma máquina estiver aberta, a luz de aviso acende.
  • NOR: a regra “nada disso aconteceu”. Uma luz verde de “tudo certo” que só acende quando nem fumaça nem gás são detectados.
  • XOR: o interruptor three-way de uma escada. Mudar o interruptor de baixo ou o de cima muda o estado da lâmpada; a lâmpada fica acesa quando os dois interruptores estão em posições diferentes e apagada quando estão iguais.
  • XNOR: uma verificação de igualdade. Ela dá 1 quando dois bits são iguais; é usada em comparadores digitais e circuitos de verificação de erros.

CIs de portas lógicas: 74HC08, 74HC32, 74HC00

Em vez de montar portas lógicas com transistores avulsos, você usa chips prontos. A família mais comum na eletrônica hobby é a série 74HC: um encapsulamento DIP de 14 pinos traz quatro portas de duas entradas, a alimentação vai sempre ao pino 14 (VCC) e o terra ao pino 7 (GND). Os chips 74HC funcionam de 2 a 6 V, as entradas quase não consomem corrente e, em 5 V, uma porta tem um atraso de cerca de 10 nanossegundos, centenas de vezes mais rápido que uma única chamada de digitalWrite no Arduino. Cada saída mantém os níveis de tensão garantidos com uma carga de 4 mA; o limite absoluto é de 25 mA por saída e 50 mA para o chip inteiro.

ChipPortaContémPinagemEquivalente CMOS 4000
74HC08AND4 × 2 entradasPadrão (tabela abaixo)CD4081
74HC32OR4 × 2 entradasPadrãoCD4071
74HC00NAND4 × 2 entradasPadrãoCD4011
74HC86XOR4 × 2 entradasPadrãoCD4070
74HC02NOR4 × 2 entradasDiferente: saídas em 1, 4, 10, 13CD4001
74HC04NOT6 × 1 entradaEntradas em 1, 3, 5, 9, 11, 13CD4069
74HC14NOT (Schmitt trigger)6 × 1 entradaIgual à do 74HC04CD40106
CD4077 / 74HCS7266XNOR4 × 2 entradasDifícil de achar; normalmente 74HC86 + 74HC04CD4077

O 74HC08, o 74HC32, o 74HC00 e o 74HC86 têm exatamente a mesma pinagem; só muda o tipo de porta dentro. O entalhe ou pontinho em cima do chip marca o pino 1. Olhando o chip de cima com o entalhe à esquerda, os pinos são numerados no sentido anti-horário: a fileira de baixo vai de 1 a 7 da esquerda para a direita e a de cima de 8 a 14 da direita para a esquerda. A e B são entradas, Y é a saída, e o dígito inicial é o número da porta.

PinoFunçãoPinoFunção
11A (entrada da porta 1)14VCC (+2…6 V)
21B (entrada da porta 1)134B (entrada da porta 4)
31Y (saída da porta 1)124A (entrada da porta 4)
42A (entrada da porta 2)114Y (saída da porta 4)
52B (entrada da porta 2)103B (entrada da porta 3)
62Y (saída da porta 2)93A (entrada da porta 3)
7GND83Y (saída da porta 3)
Nunca deixe entradas CMOS flutuando. Ligue as entradas das portas sem uso ao GND (ou ao VCC); uma entrada flutuante fica mudando com o ruído, aumenta o consumo de corrente do chip e pode até atrapalhar as portas vizinhas. Já as saídas sem uso podem ficar abertas. Não esqueça um capacitor cerâmico de 100 nF entre VCC e GND, o mais perto possível do chip.

Chips que fazem o mesmo trabalho vêm em famílias diferentes. A série 74LS é a tecnologia TTL mais antiga: ela só funciona com 4,75–5,25 V, consome mais corrente e normalmente lê uma entrada flutuante como 1. A série 74HCT é um 74HC com entradas compatíveis com TTL; funciona com 5 V, mas aceita qualquer valor a partir de 2 V como 1 garantido, então lê sem problema sinais de 3,3 V de um ESP32 ou Pico. A série CD4000 (CD4081, CD4011 e assim por diante) funciona em uma faixa ampla de 3–18 V, mas é mais lenta, e a pinagem dela é diferente da do 74HC: um CD4011 não substitui simplesmente um 74HC00.

Experimento na protoboard com botões: uma porta AND com o 74HC08

A melhor forma de entender uma porta lógica é testá-la você mesmo com dois botões. Não há microcontrolador neste experimento; você só vai precisar de um 74HC08, dois botões, dois resistores de 10 kΩ, um resistor de 1 kΩ, um LED e um capacitor de 100 nF. Para a alimentação, os pinos 5V e GND do Arduino, um módulo de alimentação para protoboard ou três pilhas AA (4,5 V) servem. Se não tem certeza de como uma protoboard é ligada por dentro, leia antes O que é uma protoboard?.

Botão para o experimento na protoboard
Um botão liga os seus dois lados enquanto está pressionado. Nos modelos de quatro pernas, as pernas são ligadas internamente aos pares, então colocar o botão atravessando o canal do meio é a opção mais segura.
  1. Encaixe o 74HC08 atravessando o canal no meio da protoboard, para que os pinos fiquem um de cada lado, com o entalhe virado para a esquerda.
  2. Ligue o pino 14 ao barramento + (5 V) e o pino 7 ao barramento − (GND) e coloque o capacitor de 100 nF entre esses dois pinos.
  3. Ligue um lado do botão A ao barramento + e o outro lado ao pino 1. Acrescente um resistor de 10 kΩ do mesmo pino ao GND: esse resistor de pull-down mantém a entrada firme em 0 enquanto o botão não está pressionado.
  4. Ligue o botão B ao pino 2 do mesmo jeito e dê a ele o seu próprio resistor de pull-down de 10 kΩ.
  5. Do pino 3, a saída, passe por um resistor de 1 kΩ até a perna longa (ânodo) do LED; ligue a perna curta (cátodo) do LED ao GND.
  6. Ligue as entradas sem uso, os pinos 4, 5, 9, 10, 12 e 13, ao GND; deixe as saídas 6, 8 e 11 abertas.
  7. Ligue a alimentação e teste as quatro combinações, uma de cada vez: o LED só deve acender quando você aperta os dois botões juntos. Compare os resultados com a tabela-verdade.
LigaçãoPino do 74HC08Ligar em
Alimentação14 (VCC)Barramento +, 5 V
Terra7 (GND)Barramento −
Capacitor de desacoplamentoEntre 14 e 7Cerâmico de 100 nF, perto do chip
Entrada A1Botão A → 5 V, 10 kΩ → GND
Entrada B2Botão B → 5 V, 10 kΩ → GND
Saída31 kΩ → ânodo do LED, cátodo do LED → GND
Entradas sem uso4, 5, 9, 10, 12, 13GND
Saídas sem uso6, 8, 11Abertas
Quando o circuito funcionar, começa a parte divertida: tire o 74HC08 e coloque um 74HC32, que tem a mesma pinagem, e o LED acende quando você aperta qualquer um dos botões (OR). Com um 74HC00, ele fica aceso até você apertar os dois botões juntos (NAND), e com um 74HC86 ele só acende quando você aperta um único botão (XOR). Com um resistor de 1 kΩ, um LED vermelho consome cerca de 3 mA, um valor seguro para uma saída 74HC. Para outra cor de LED, você pode calcular o resistor com a ferramenta Resistor para LED.

Montando todas as portas com NAND: a porta universal

A NAND é chamada de porta universal porque você consegue montar todas as outras portas usando só portas NAND. Isso também tem um lado prático: na tecnologia CMOS, a NAND é uma das portas mais simples, precisando de só 4 transistores, enquanto uma AND é na verdade uma NAND seguida de uma NOT e precisa de 6. Por isso os projetistas de chips adoram a NAND. A memória flash NAND dos pen drives também ganhou esse nome pela forma como as células de memória são ligadas em série, como os transistores de uma porta NAND. A NOR também é universal: o Computador de Orientação da Apollo, que foi à Lua, foi construído com cerca de 2.800 chips, cada um com duas portas NOR de três entradas.

Porta a montarComo fazer com NAND?NANDs necessárias
NOTA NAND A (ligue as duas entradas juntas)1
ANDPasse a saída de (A NAND B) por uma NOT2
OR(A NAND A) NAND (B NAND B)3
NOROR + NOT4
XORN1 = A NAND B; (A NAND N1) NAND (B NAND N1)4
XNORXOR + NOT5

A linha OR da tabela se baseia na lei de De Morgan: (A' · B')' = A + B. Ou seja, se você inverter primeiro as duas entradas e depois colocá-las em uma NAND, obtém uma OR. A segunda lei de De Morgan é (A + B)' = A' · B'. As duas leis também ajudam a simplificar condições no código: no Arduino, !(a && b) sempre dá o mesmo resultado que (!a || !b), e !(a || b) o mesmo que (!a && !b).

Montar uma XOR com quatro portas NAND é um exercício clássico de prova e de laboratório, e as quatro portas de um único 74HC00 bastam exatamente. Primeiro calcula-se N1 = A NAND B. Depois encontram-se N2 = A NAND N1 e N3 = B NAND N1, e a saída da última porta, Y = N2 NAND N3, dá a XOR. Com a ligação abaixo, você transforma o seu experimento na protoboard em uma XOR de quatro NANDs:

Pino do 74HC00LigaçãoPapel
1 e 4Botão AEntrada A (portas 1 e 2)
2 e 10Botão BEntrada B (portas 1 e 3)
3 → 5 e 9JumperN1 = A NAND B
6 → 12JumperN2 = A NAND N1
8 → 13JumperN3 = B NAND N1
111 kΩ + LEDY = A XOR B
14 / 75 V / GNDAlimentação

Vamos um passo além: se você cruzar as saídas de duas portas NAND com as entradas uma da outra, obtém uma memória de 1 bit chamada latch SR. Esse circuito lembra o último estado mesmo depois que você solta o botão. Os registradores dos processadores, os contadores e chips como o registrador de deslocamento 74HC595 são feitos encadeando células de memória como essa, construídas com portas.

O meio somador: somando dois bits com portas

A coisa mais impressionante que as portas lógicas conseguem fazer é somar números. Em binário, 0 + 0 = 0, 0 + 1 = 1, 1 + 0 = 1 e 1 + 1 = 10 (2 em decimal). O dígito da direita do resultado se chama soma, e o dígito que transborda para a esquerda é o vai-um (carry). Olhando a tabela abaixo, você vê que a soma é exatamente a XOR e o vai-um é exatamente a AND. Então uma porta XOR e uma porta AND lado a lado formam um meio somador, que soma dois números de um bit.

ABVai-um (C = A AND B)Soma (S = A XOR B)Resultado em decimal
00000
01011
10011
11102 (10 em binário)

Para montá-lo na protoboard, ligue os botões A e B aos pinos 1 e 2 de um 74HC86 e de um 74HC08. O pino 3 do 74HC86 aciona o LED da soma e o pino 3 do 74HC08, o LED do vai-um. Quando você aperta os dois botões, o LED da soma apaga e o do vai-um acende: os LEDs estão mostrando 10 em binário, ou seja, 2. Se quiser usar só um 74HC00, você precisa de quatro NANDs para a XOR e de uma quinta NAND que inverte o N1 para obter o vai-um; ou seja, um meio somador leva 5 portas NAND.

Um meio somador não consegue levar em conta um vai-um vindo do dígito de baixo; para isso você precisa de um somador completo. As fórmulas dele são S = A ⊕ B ⊕ Cin e Cout = (A · B) + (Cin · (A ⊕ B)), o que significa dois meios somadores mais uma porta OR. Encadeie quatro somadores completos, cada um passando o seu vai-um para o seguinte, e você tem um somador de 4 bits; o chip pronto 74HC283 faz a mesma soma de 4 bits, mas calcula os vai-uns com um circuito interno rápido (carry look-ahead), em vez de esperar que eles se propaguem pela cadeia. A unidade aritmética do processador do seu computador é uma versão de 64 bits, muito mais rápida, da mesma ideia.

Portas lógicas no Arduino: &&, ||, ! e operações bit a bit

No código do Arduino, cada porta lógica tem dois equivalentes. Os operadores lógicos (&&, ||, !) combinam condições e dão um resultado verdadeiro ou falso; você os usa em instruções if e while. Os operadores bit a bit (&, |, ^, ~) são aplicados a todos os bits de um número de uma vez, coluna por coluna; trabalhar com um byte é como rodar oito portas ao mesmo tempo. Os exemplos da tabela usam os números 0b1100 e 0b1010:

PortaLógico (bool)Bit a bitExemploResultado
ANDa && bx & y0b1100 & 0b10100b1000
ORa || bx | y0b1100 | 0b10100b1110
NOT!a~x~0b00001100 (byte)0b11110011
NAND!(a && b)~(x & y)~(0b1100 & 0b1010) & 0x0F0b0111
NOR!(a || b)~(x | y)~(0b1100 | 0b1010) & 0x0F0b0001
XORa != bx ^ y0b1100 ^ 0b10100b0110
XNORa == b~(x ^ y)~(0b1100 ^ 0b1010) & 0x0F0b1001

A diferença entre os dois tipos parece pequena, mas causa bugs traiçoeiros. && e || usam avaliação em curto-circuito: em a && b, se a for falso, b nunca é avaliado. O & sempre avalia os dois lados e olha os bits dos números: 2 && 1 é verdadeiro, mas 2 & 1 é 0, porque 0b10 e 0b01 não têm nenhum bit em comum. O C++ não tem um operador XOR lógico separado; para dois bools, escrever a != b é a forma mais legível. Para saber mais sobre operações bit a bit, os deslocamentos << e >> e o sistema binário, veja Sistemas numéricos e operações com bits.

Agora vamos levar o experimento da protoboard para um Arduino Uno. Dois botões vão aos pinos 2 e 3, e sete LEDs (cada um com um resistor de 330 Ω) aos pinos 4–10. Um lado de cada botão vai ao pino e o outro ao GND; como o resistor de pull-up interno está ativado, não é preciso resistor extra. Um único sketch dá vida às sete portas de uma vez:

C++ (Arduino IDE)
1// Mantık kapısı simülatörü: 2 buton, 7 LED / Logic gate simulator: 2 buttons, 7 LEDs
2const byte PIN_A = 2;   // A butonu, diğer ucu GND / button A, other leg to GND
3const byte PIN_B = 3;   // B butonu, diğer ucu GND / button B, other leg to GND
4
5// Sıra: AND, OR, NOT A, NAND, NOR, XOR, XNOR / Order: AND, OR, NOT A, NAND, NOR, XOR, XNOR
6const byte LED_PINS[7] = {4, 5, 6, 7, 8, 9, 10};
7const char* const GATE_NAMES[7] = {"AND", "OR", "NOT A", "NAND", "NOR", "XOR", "XNOR"};
8
9byte lastInputs = 0xFF;   // ilk turda yazdırmayı zorlar / forces a print on the first pass
10
11void setup() {
12  pinMode(PIN_A, INPUT_PULLUP);
13  pinMode(PIN_B, INPUT_PULLUP);
14  for (byte i = 0; i < 7; i++) {
15    pinMode(LED_PINS[i], OUTPUT);
16  }
17  Serial.begin(9600);
18}
19
20void loop() {
21  // Basılı buton LOW okunur, ! ile 1 yapılır / A pressed button reads LOW, ! turns it into 1
22  bool a = !digitalRead(PIN_A);
23  bool b = !digitalRead(PIN_B);
24
25  bool out[7];
26  out[0] = a && b;      // AND
27  out[1] = a || b;      // OR
28  out[2] = !a;          // NOT A
29  out[3] = !(a && b);   // NAND
30  out[4] = !(a || b);   // NOR
31  out[5] = a != b;      // XOR: girişler farklı mı? / are the inputs different?
32  out[6] = a == b;      // XNOR: girişler aynı mı? / are the inputs equal?
33
34  for (byte i = 0; i < 7; i++) {
35    digitalWrite(LED_PINS[i], out[i] ? HIGH : LOW);
36  }
37
38  // Yalnız girişler değişince yaz / Print only when the inputs change
39  byte inputs = (a << 1) | b;
40  if (inputs != lastInputs) {
41    Serial.print("A=");
42    Serial.print(a);
43    Serial.print(" B=");
44    Serial.print(b);
45    for (byte i = 0; i < 7; i++) {
46      Serial.print("  ");
47      Serial.print(GATE_NAMES[i]);
48      Serial.print('=');
49      Serial.print(out[i]);
50    }
51    Serial.println();
52    lastInputs = inputs;
53  }
54  delay(20);   // basit sıçrama önleme / simple debounce
55}

Com INPUT_PULLUP, um botão pressionado lê LOW, então o código inverte a leitura com ! e um botão pressionado vira 1. Cada LED mostra então o resultado da sua porta: 4 AND, 5 OR, 6 NOT A, 7 NAND, 8 NOR, 9 XOR e 10 XNOR. Se você abrir o Monitor Serial em 9600 baud, a linha inteira é mostrada sempre que um botão muda; depois de testar as quatro combinações, você produziu a tabela-verdade com as próprias mãos. Os detalhes do pull-up estão em Como ligar um botão ao Arduino.

Para ver o poder das operações bit a bit, o segundo exemplo calcula a tabela-verdade inteira em poucas linhas. O truque: se você escrever a coluna A como o número 0b1100 e a coluna B como 0b1010, cada bit corresponde a uma linha da tabela, e um único & dá as quatro linhas da coluna AND de uma vez. A segunda metade do sketch soma dois números de 4 bits, bit a bit, usando as fórmulas do somador completo, imitando em software o circuito somador de um processador. Esse sketch não precisa de hardware; basta abrir o Monitor Serial.

C++ (Arduino IDE)
1// Bit işlemleriyle doğruluk tablosu ve 4 bitlik toplayıcı / Truth tables with bitwise ops and a 4-bit adder
2// Her bit bir satırdır: bit 0 = (A=0, B=0) ... bit 3 = (A=1, B=1) / Each bit is one row: bit 0 = (A=0, B=0) ... bit 3 = (A=1, B=1)
3const byte COL_A = 0b1100;
4const byte COL_B = 0b1010;
5const byte MASK  = 0b1111;   // yalnız 4 satır / only 4 rows
6
7void printRow(const char* name, byte column) {
8  Serial.print(name);
9  Serial.print('\t');
10  for (byte row = 0; row < 4; row++) {
11    Serial.print(bitRead(column, row));   // satır satır yaz / print row by row
12    Serial.print("  ");
13  }
14  Serial.println();
15}
16
17// Tam toplayıcı: iki bit + gelen elde / Full adder: two bits + carry in
18void fullAdder(byte a, byte b, byte carryIn, byte &sum, byte &carryOut) {
19  sum = a ^ b ^ carryIn;                         // XOR'lar toplamı verir / XORs give the sum
20  carryOut = (a & b) | (carryIn & (a ^ b));      // AND + OR eldeyi verir / AND + OR give the carry
21}
22
23// 4 tam toplayıcı zincirlenir (ripple carry) / 4 full adders chained (ripple carry)
24byte add4(byte x, byte y, byte &carryOut) {
25  byte result = 0;
26  byte carry = 0;
27  for (byte i = 0; i < 4; i++) {
28    byte s, c;
29    fullAdder(bitRead(x, i), bitRead(y, i), carry, s, c);
30    bitWrite(result, i, s);
31    carry = c;
32  }
33  carryOut = carry;
34  return result;
35}
36
37void setup() {
38  Serial.begin(9600);
39  Serial.println(F("AB:\t00 01 10 11"));
40  printRow("AND",  COL_A & COL_B);
41  printRow("OR",   COL_A | COL_B);
42  printRow("NAND", ~(COL_A & COL_B) & MASK);   // ~ sonrası maske şart / mask is required after ~
43  printRow("NOR",  ~(COL_A | COL_B) & MASK);
44  printRow("XOR",  COL_A ^ COL_B);
45  printRow("XNOR", ~(COL_A ^ COL_B) & MASK);
46
47  byte carry;
48  byte s = add4(9, 12, carry);   // 1001 + 1100
49  Serial.print(F("9 + 12 = "));
50  Serial.print(s + carry * 16);  // elde 16'lar basamağıdır / the carry is the 16s place
51  Serial.print(F("  (toplam / sum = "));
52  Serial.print(s, BIN);
53  Serial.print(F(", elde / carry = "));
54  Serial.print(carry);
55  Serial.println(')');
56}
57
58void loop() {
59}
Não use ~ em valores bool: o ~ inverte todos os bits e transforma true (1) em -2, e como -2 não é zero, continua contando como verdadeiro. Use sempre ! para um NOT lógico. Outra armadilha é a precedência dos operadores: em if (x & 1 == 0), 1 == 0 é avaliado primeiro, então a forma correta é if ((x & 1) == 0). Além disso, aplicar ~ a uma variável byte promove o resultado para int, então corte-o com uma máscara como & 0x0F ou & 0xFF, como o código faz.

Um testador de chips 74HC com Arduino

Se as marcações de um chip se apagaram, ou se você quer saber se ele ainda funciona, pode transformar o Arduino em um testador. Este sketch aplica as quatro combinações de entrada, uma de cada vez, nas quatro portas de um 74HC00, 74HC08, 74HC32 ou 74HC86 (os chips com a pinagem padrão), lê as saídas e compara o resultado com padrões conhecidos. Ligue o pino 14 do chip ao 5V, o pino 7 ao GND e os outros pinos aos pinos do Arduino listados na tabela do código.

C++ (Arduino IDE)
1// 74HC00 / 08 / 32 / 86 tanıyıcı ve test cihazı / 74HC00 / 08 / 32 / 86 identifier and tester
2// Entegre: bacak 14 -> 5V, bacak 7 -> GND / Chip: pin 14 -> 5V, pin 7 -> GND
3// Her kapı: {A, B, Y} Arduino pinleri / Each gate: {A, B, Y} Arduino pins
4const byte GATES[4][3] = {
5  {2, 3, 4},      // kapı 1: entegre 1, 2 -> 3 / gate 1: chip 1, 2 -> 3
6  {5, 6, 7},      // kapı 2: entegre 4, 5 -> 6 / gate 2: chip 4, 5 -> 6
7  {8, 9, 10},     // kapı 3: entegre 9, 10 -> 8 / gate 3: chip 9, 10 -> 8
8  {11, 12, A0}    // kapı 4: entegre 12, 13 -> 11 / gate 4: chip 12, 13 -> 11
9};
10
11// Desenin bit sırası: bit 0 = (0,0), bit 3 = (1,1) / Pattern bit order: bit 0 = (0,0), bit 3 = (1,1)
12const char* nameOf(byte pattern) {
13  switch (pattern) {
14    case 0b1000: return "AND (74HC08)";
15    case 0b1110: return "OR (74HC32)";
16    case 0b0111: return "NAND (74HC00)";
17    case 0b0110: return "XOR (74HC86)";
18    default:     return "?";
19  }
20}
21
22byte testGate(byte g) {
23  byte pattern = 0;
24  for (byte row = 0; row < 4; row++) {
25    digitalWrite(GATES[g][0], bitRead(row, 1));   // A = satırın üst biti / A = high bit of the row
26    digitalWrite(GATES[g][1], bitRead(row, 0));   // B = satırın alt biti / B = low bit of the row
27    delayMicroseconds(10);                        // kapı ~10 ns gecikir, bol pay / the gate needs ~10 ns, plenty of margin
28    bitWrite(pattern, row, digitalRead(GATES[g][2]));
29  }
30  return pattern;
31}
32
33void setup() {
34  Serial.begin(9600);
35  for (byte g = 0; g < 4; g++) {
36    pinMode(GATES[g][0], OUTPUT);
37    pinMode(GATES[g][1], OUTPUT);
38    pinMode(GATES[g][2], INPUT);
39  }
40
41  byte first = testGate(0);
42  bool allSame = true;
43  for (byte g = 0; g < 4; g++) {
44    byte p = testGate(g);
45    Serial.print(F("Kapi / Gate "));
46    Serial.print(g + 1);
47    Serial.print(F(": "));
48    Serial.print(nameOf(p));
49    Serial.print(F("  desen / pattern 0b"));
50    Serial.println(p, BIN);
51    if (p != first) allSame = false;
52  }
53
54  if (allSame && nameOf(first)[0] != '?') {
55    Serial.println(F("Sonuc / Result: entegre saglam / chip OK"));
56  } else {
57    Serial.println(F("Sonuc / Result: bozuk kapi ya da baglanti hatasi / faulty gate or wiring error"));
58  }
59}
60
61void loop() {
62}
Se você errar a ligação, uma saída do Arduino pode acabar brigando com uma saída do chip. Para evitar isso, você pode colocar um resistor de 1 kΩ entre as saídas do chip (3, 6, 8, 11) e os pinos do Arduino; o resultado do teste não muda, mas os dois lados ficam protegidos se algo estiver ligado errado. O 74HC02 e o 74HC04 têm pinagem diferente, então este sketch não os testa diretamente; você precisaria mudar a tabela GATES conforme os datasheets deles.

Uma porta lógica programável com o ESP32

Os mesmos operadores funcionam sem mudanças no ESP32. Neste exemplo, um terceiro botão percorre os tipos de porta, e um único LED mostra a saída da porta selecionada. Assim você consegue demonstrar seis portas com um só circuito em uma aula ou apresentação. Os botões vão aos GPIO 25, 26 e 27 (o outro lado deles ao GND), e o LED vai ao GPIO 23 através de um resistor de 220 Ω; o nome da porta selecionada aparece no Monitor Serial em 115200 baud.

C++ (Arduino IDE)
1// ESP32 programlanabilir mantık kapısı / ESP32 programmable logic gate
2const int PIN_A = 25;      // A butonu, diğer ucu GND / button A, other leg to GND
3const int PIN_B = 26;      // B butonu / button B
4const int PIN_MODE = 27;   // kapı seçme butonu / gate select button
5const int PIN_LED = 23;    // çıkış LED'i (220 ohm) / output LED (220 ohm)
6
7const char* const NAMES[] = {"AND", "OR", "NAND", "NOR", "XOR", "XNOR"};
8const int GATE_COUNT = 6;
9const unsigned long DEBOUNCE_MS = 30;   // sıçrama süresi / bounce time
10
11int gate = 0;
12int modeStable = HIGH;            // kararlı buton durumu / stable button state
13int modeRaw = HIGH;               // son ham okuma / last raw reading
14unsigned long modeChangedAt = 0;  // ham değerin son değiştiği an / when the raw value last changed
15
16bool evaluate(int g, bool a, bool b) {
17  switch (g) {
18    case 0:  return a && b;
19    case 1:  return a || b;
20    case 2:  return !(a && b);
21    case 3:  return !(a || b);
22    case 4:  return a != b;     // XOR
23    default: return a == b;     // XNOR
24  }
25}
26
27void setup() {
28  Serial.begin(115200);
29  pinMode(PIN_A, INPUT_PULLUP);
30  pinMode(PIN_B, INPUT_PULLUP);
31  pinMode(PIN_MODE, INPUT_PULLUP);
32  pinMode(PIN_LED, OUTPUT);
33  Serial.printf("Kapi / Gate: %s\n", NAMES[gate]);
34}
35
36void loop() {
37  int reading = digitalRead(PIN_MODE);
38  if (reading != modeRaw) {          // ham değer değişti, süreyi yeniden başlat / raw value changed, restart the timer
39    modeRaw = reading;
40    modeChangedAt = millis();
41  }
42  // 30 ms boyunca sabit kaldıysa gerçek değişimdir / steady for 30 ms means a real change
43  if (millis() - modeChangedAt > DEBOUNCE_MS && reading != modeStable) {
44    modeStable = reading;
45    if (modeStable == LOW) {         // yeni basış (bırakma sayılmaz) / new press (release is ignored)
46      gate = (gate + 1) % GATE_COUNT;
47      Serial.printf("Kapi / Gate: %s\n", NAMES[gate]);
48    }
49  }
50
51  bool a = !digitalRead(PIN_A);   // basılı = 1 / pressed = 1
52  bool b = !digitalRead(PIN_B);
53  digitalWrite(PIN_LED, evaluate(gate, a, b) ? HIGH : LOW);
54}
O ESP32 e o Pico trabalham em 3,3 V, e os pinos deles não toleram 5 V. Se você usar um chip 74HC com essas placas, alimente-o também com 3,3 V; um 74HC funciona a partir de 2 V, então isso não é problema. Se o chip for alimentado com 5 V, os 5 V na saída dele podem danificar a entrada da placa; no sentido contrário, um sinal de 3,3 V fica abaixo de 3,5 V, o limite de 1 garantido de um 74HC funcionando em 5 V. Se você precisa conversar com um circuito de 5 V, use um chip 74HCT ou um conversor de nível lógico.

Portas lógicas com o Raspberry Pi Pico e MicroPython

No MicroPython, os operadores lógicos são escritos como palavras em inglês: and, or, not. Os operadores bit a bit são os mesmos do C++: &, |, ^ e ~. O código abaixo lê dois botões no GP14 e no GP15 e mostra os resultados de AND, OR, NAND, NOR, XOR e XNOR em seis LEDs nos GP16–GP21. O outro lado de cada botão vai ao GND, e cada LED é ligado através de um resistor de 220–330 Ω. Se você salvar o código no Thonny como main.py, ele roda toda vez que o Pico liga; se o Pico é novidade para você, comece por O que é o Raspberry Pi Pico?.

MicroPython
1# Pico ile 6 mantık kapısı / 6 logic gates on the Pico
2from machine import Pin
3import time
4
5btn_a = Pin(14, Pin.IN, Pin.PULL_UP)   # A butonu, diğer ucu GND / button A, other leg to GND
6btn_b = Pin(15, Pin.IN, Pin.PULL_UP)   # B butonu / button B
7
8# GP16..GP21: AND, OR, NAND, NOR, XOR, XNOR
9leds = [Pin(n, Pin.OUT) for n in range(16, 22)]
10gates = [
11    ("AND",  lambda a, b: a and b),
12    ("OR",   lambda a, b: a or b),
13    ("NAND", lambda a, b: not (a and b)),
14    ("NOR",  lambda a, b: not (a or b)),
15    ("XOR",  lambda a, b: a != b),
16    ("XNOR", lambda a, b: a == b),
17]
18
19last = None
20while True:
21    a = int(not btn_a.value())   # basılı = 1 / pressed = 1
22    b = int(not btn_b.value())
23    results = [int(f(a, b)) for _, f in gates]
24    for led, r in zip(leds, results):
25        led.value(r)
26    if (a, b) != last:           # yalnız değişince yaz / print only on change
27        line = " ".join("%s=%d" % (g[0], r) for g, r in zip(gates, results))
28        print("A=%d B=%d  %s" % (a, b, line))
29        last = (a, b)
30    time.sleep_ms(20)

O Python tem uma armadilha parecida: ~True dá -2, porque um bool na verdade é um inteiro. Para inverter um bit, use not x, 1 - x ou x ^ 1. Além disso, os operadores and e or do Python nem sempre retornam True ou False; eles retornam o último valor avaliado, então 0 or 5 dá 5. É por isso que o código usa conversões int(), para que os LEDs só recebam 0 ou 1.

Ideias de projetos com portas lógicas

  • Luz noturna inteligente (AND): acenda a luz quando estiver escuro E houver movimento; combine um LDR e um sensor PIR em uma única condição &&.
  • Luz de escada (XOR): controle uma lâmpada com dois botões, um embaixo e outro em cima da escada; calcule o estado da lâmpada com XOR e chaveie a lâmpada da rede elétrica com um módulo relé.
  • Alarme residencial (AND + OR): com o sistema armado, toque a sirene se a porta OU a janela abrir. Detecte a porta e a janela com um reed switch; veja o guia Sistema de alarme com Arduino para os detalhes.
  • Cofre de duas chaves (AND): não deixe a fechadura abrir a não ser que duas pessoas diferentes apertem os seus botões ao mesmo tempo, ou até que a senha do teclado matricial seja confirmada.
  • Calculadora de 4 bits: some dois números digitados com chaves usando a lógica do somador completo e mostre o resultado em um display de 7 segmentos.
  • Campainha de quiz: trave o LED do primeiro participante que apertar e bloqueie os outros; essa é a versão em software de um latch baseado em NAND.
  • Verificação de paridade: faça a XOR de todos os bits de um byte; se o resultado for 1, a quantidade de 1s é ímpar. O bit de paridade da comunicação serial é calculado exatamente assim.

Erros comuns e como corrigi-los

SintomaCausa provávelSolução
O LED pisca sozinho e muda quando você aproxima a mãoEntrada flutuante, sem resistor de pull-downColoque um resistor de pull-down ou pull-up de 10 kΩ em cada entrada
O chip esquentaVCC e GND trocados, ou duas saídas ligadas juntasO pino 14 deve ser VCC e o 7, GND; nunca una saídas
Nenhuma porta respondeSem alimentação, ou o chip não está atravessando o canalMeça entre os pinos 14 e 7 com um multímetro, encaixe o chip atravessando o canal
Resultados errados com um 74HC02 ou CD4011A pinagem dele é diferente da do 74HC08Ligue conforme a tabela de pinos do datasheet
O chip consome mais corrente do que deveriaEntradas sem uso deixadas flutuandoLigue todas as entradas sem uso ao GND
Resultados instáveis com ESP32 ou PicoUm sinal de 3,3 V não basta para um 74HC em 5 VAlimente o 74HC com 3,3 V ou use um 74HCT
if (a & b) é falso sem motivo aparenteO & funciona bit a bit; 2 & 1 = 0Use && nas condições
if (x & 1 == 0) nunca é executadoO == é avaliado antes do &Use parênteses: (x & 1) == 0
Um toque muda a porta várias vezesRepique dos contatosEspere 20–50 ms no software ou use um filtro RC + 74HC14
Antes de montar um circuito, escreva a tabela-verdade dele no papel e depois teste cada linha, uma por uma. A linha em que o LED não bate com o resultado esperado indica que o problema está na porta que aquela linha usa ou na ligação dessa porta. Deixe a ferramenta Portas lógicas aberta para conferir a tabela rapidamente, e você também pode testar o circuito no virtual no Tinkercad antes de montá-lo.

As portas lógicas são o alfabeto de todo o mundo digital, de acender um LED a um processador somando números. Quando você entende AND, OR e NOT, ler uma condição if, uma regra de alarme ou um registrador de deslocamento fica muito mais fácil. No app BlueGrays você encontra projetos de LED com botão, projetos com botões para ESP32 e Raspberry Pi Pico, um projeto de iluminação inteligente de escada e um projeto de iluminação inteligente que combina PIR e LDR, cada um com esquemas do circuito e código passo a passo, para colocar a lógica das portas deste artigo em ação em projetos reais.

Perguntas frequentes

Quais são os tipos de portas lógicas e para que servem?

Existem sete portas lógicas básicas: AND, OR, NOT, NAND, NOR, XOR e XNOR. Cada uma olha entradas que são 0 ou 1 e gera uma única saída segundo a sua própria regra. Todo circuito digital, incluindo processadores, memórias, contadores e calculadoras, é feito combinando essas portas.

Como fazer uma tabela-verdade?

Primeiro calcule o número de linhas a partir do número de entradas: n entradas precisam de 2ⁿ linhas. Escreva as entradas na ordem da contagem binária (00, 01, 10, 11) e depois aplique a regra da porta a cada linha para preencher a coluna de saída. Em circuitos com várias portas, acrescentar uma coluna separada para cada saída intermediária facilita o trabalho.

Por que a NAND é chamada de porta universal?

Porque você consegue montar NOT, AND, OR, NOR, XOR e XNOR usando só portas NAND. Por exemplo, ligar as duas entradas de uma NAND juntas dá uma NOT, duas NANDs em sequência dão uma AND e quatro NANDs dão uma XOR. A porta NOR tem a mesma propriedade, então também conta como porta universal.

Qual é a diferença entre XOR e XNOR?

A XOR dá 1 quando as entradas são diferentes, enquanto a XNOR dá 1 quando as entradas são iguais. A XNOR é o inverso da XOR e é usada para verificar se dois bits são iguais. A XOR é usada em circuitos somadores, em verificações de paridade e para inverter um bit.

Qual é a diferença entre o 74HC08 e o 74LS08?

Os dois têm quatro portas AND de duas entradas e a mesma pinagem. O 74HC08 é feito com tecnologia CMOS, funciona de 2–6 V e consome pouquíssima corrente; o 74LS08 é TTL, só funciona por volta de 5 V e consome mais corrente. Em projetos novos, escolha o 74HC, e o 74HCT quando for ligar sinais de 3,3 V a um circuito de 5 V.

Qual é a diferença entre && e & no Arduino?

&& é o operador AND lógico; ele verifica se as duas condições são verdadeiras e retorna true ou false. & é o AND bit a bit e compara separadamente cada bit de dois números. Por isso 2 && 1 é verdadeiro, mas 2 & 1 é 0; use && nas condições if.

Ver todos os projetos
Controle de LED com botão (momentâneo)
#9Iniciante

Controle de LED com botão (momentâneo)

É como uma campainha: a luz fica acesa enquanto você pressiona o botão e apaga quando você solta. O Arduino monitora o botão continuamente; enquanto ele está pressionado, o LED fica aceso e apaga assi

4.8(113)
229
Ligar e desligar um LED com botão
#10Iniciante

Ligar e desligar um LED com botão

Pressione o botão uma vez para acender a luz e outra vez para apagar, como o interruptor do seu quarto. O Arduino detecta cada toque e inverte o estado do LED, aguardando um breve instante para que as

4.8(100)
167
Controle de LED com botão no ESP32 (momentâneo)
#104Iniciante

Controle de LED com botão no ESP32 (momentâneo)

O LED acende enquanto o botão está pressionado e apaga ao soltá-lo. Mostra como usar o pino de entrada digital e o resistor pull-up interno do ESP32. O modo INPUT_PULLUP dispensa um resistor externo.

4.6(36)
55
Controle de LED com botão no ESP32 (alternância)
#105Iniciante

Controle de LED com botão no ESP32 (alternância)

Cada vez que o botão é pressionado, o estado do LED muda: se estiver aceso, apaga; se estiver apagado, acende. É o padrão clássico de alternância. Com debounce, eliminamos o ruído mecânico dos contatos do botão para garantir uma única mudança a cada pressionamento.

4.6(39)
57
Raspberry Pi Pico: LED controlado por botão (enquanto pressionado)
#155Iniciante
Premium

Raspberry Pi Pico: LED controlado por botão (enquanto pressionado)

Primeiro projeto de entrada com o Pico — leitura de botão! O LED acende enquanto o botão está pressionado e apaga ao soltá-lo. O grande passo depois das animações com LEDs: entrada de sinais do mundo para o Pico. Aprenda a usar Pin.IN (modo de entrada), Pin.PULL_UP (pull-up interno — padrão para botões) e a leitura com button.value(). LED no GP14, botão no GP2. Pressionado = LOW (0), solto = HIGH (1) — essa lógica invertida confunde no início, mas é padrão da indústria.

0.0(0)
11
Raspberry Pi Pico: controle independente de 2 LEDs com 2 botões
#157Iniciante
Premium

Raspberry Pi Pico: controle independente de 2 LEDs com 2 botões

2 botões, 2 LEDs — totalmente independentes! Cada botão controla seu próprio LED: ao pressionar BTN1, o LED vermelho acende; ao pressionar BTN2, o LED verde acende. Se você pressionar os dois ao mesmo tempo, ambos os LEDs acendem (operação em paralelo). Aprenda gerenciamento de vários objetos Pin (várias entradas e saídas ao mesmo tempo), operador ternário (1 if x else 0 — if-else compacto do Python), controle independente de I/O (lógica de operação em paralelo) e mapa de GPIO…

0.0(0)
7
Iluminação inteligente de escadas e corredores
#82Intermediário
Premium

Iluminação inteligente de escadas e corredores

Ao entrar na escada ou no corredor, as luzes acendem uma a uma no sentido em que você caminha. Há um sensor de distância em cada extremidade; ao passar por um deles, os oito LEDs acendem a partir daqu

5.0(35)
51
Iluminação inteligente com ESP32 (PIR + LDR + relé + OLED)
#141Avançado
Premium

Iluminação inteligente com ESP32 (PIR + LDR + relé + OLED)

Transforme a iluminação do corredor, banheiro ou despensa em iluminação inteligente com ESP32! Com um sensor de movimento PIR, um sensor de luz LDR e um módulo relé, montamos o cenário clássico de "acender a luz ao detectar movimento no escuro" — se o ambiente já estiver claro, o movimento NÃO aciona a luz, economizando energia durante o dia. A luz fica acesa por 30 segundos; se o movimento continuar, o temporizador reinicia e a luz permanece acesa por mais tempo.

4.3(6)
11