Portes logiques : ET, OU, NON, XOR, table de vérité et Arduino
Les portes logiques ET, OU, NON, NAND, NOR et XOR : symboles, tables de vérité, circuits 74HC08 et 74HC00, demi-additionneur et code Arduino, ESP32 et Pico.
Les portes logiques sont les briques de base des circuits numériques : chacune observe une ou plusieurs entrées numériques et produit une seule sortie numérique selon une règle fixe. Les entrées ne peuvent valoir que 0 (LOW) ou 1 (HIGH), et la sortie aussi. Il existe sept portes de base : ET (AND), OU (OR), NON (NOT), NON-ET (NAND), NON-OU (NOR), OU exclusif (XOR) et XNOR. Du processeur de ton téléphone à la carte d'un lave-linge, de l'ATmega328P d'un Arduino à une calculatrice de poche, tous les appareils numériques fonctionnent en combinant des millions de minuscules portes logiques.
Dans ce guide, tu vas découvrir le symbole et la table de vérité de chaque porte, de vrais circuits intégrés comme les 74HC08, 74HC32 et 74HC00, une expérience à deux boutons-poussoirs sur plaque d'essai, comment construire toutes les autres portes uniquement avec des NAND, et le demi-additionneur qui additionne deux bits. Dans les dernières parties, nous traduirons la même logique en code sur Arduino avec les opérateurs &&, || et ! et avec les opérations bit à bit, puis nous continuerons avec des exemples pour l'ESP32 et le Raspberry Pi Pico (MicroPython).

Qu'est-ce qu'une porte logique et comment fonctionne-t-elle ?
En électronique numérique, chaque signal se trouve dans l'un de deux états : 1 (HIGH, vrai) ou 0 (LOW, faux). Les mathématiques qui manipulent ces deux valeurs s'appellent l'algèbre de Boole ; dans un livre publié en 1854, George Boole a exprimé le raisonnement logique sous forme d'algèbre de cette manière. En 1937, Claude Shannon a montré que cette algèbre correspond exactement aux circuits de commutation à relais, posant ainsi les bases de la conception des circuits numériques. Aujourd'hui, une porte logique ne contient que quelques transistors : en technologie CMOS, une porte NON compte 2 MOSFET et une NAND en compte 4. Nous expliquons comment un transistor fonctionne en interrupteur dans Qu'est-ce qu'un transistor ?.
Mais quelle tension le circuit considère-t-il comme un 1, et laquelle comme un 0 ? Cela dépend de la tension d'alimentation de la carte et de la famille du circuit. Le tableau ci-dessous indique les seuils à partir desquels une entrée est reconnue à coup sûr comme 1 ou comme 0. La zone entre les deux seuils est la zone indéterminée ; si une entrée y reste, la sortie peut se comporter au hasard. Une entrée reliée à rien, dite entrée flottante, erre justement dans cette zone. C'est pourquoi chaque entrée doit être reliée à un signal, ou à GND ou VCC à travers une résistance.
| Carte / famille | Alimentation | Entrée reconnue comme 1 | Entrée reconnue comme 0 |
|---|---|---|---|
| Arduino Uno (ATmega328P) | 5 V | ≥ 3,0 V | ≤ 1,5 V |
| ESP32 | 3,3 V | ≥ 2,5 V | ≤ 0,8 V |
| Raspberry Pi Pico (RP2040) | 3,3 V | ≥ 2,0 V | ≤ 0,8 V |
| Circuit 74HC | 5 V | ≥ 3,5 V | ≤ 1,5 V |
| Circuit 74HCT | 5 V | ≥ 2,0 V | ≤ 0,8 V |
| Circuit CD4000 | 5 V | ≥ 3,5 V | ≤ 1,5 V |
Les 7 portes logiques de base et leurs symboles
Sur les schémas, les portes sont dessinées selon deux normes différentes. Dans la norme américaine (ANSI/IEEE), chaque porte a sa propre forme : ET ressemble à la lettre D, OU à un bouclier pointu et NON à un triangle. Le petit rond en sortie signifie "inverser" ; une NAND est donc une porte ET avec un rond au bout. Ce qui distingue le OU exclusif du OU, c'est la deuxième ligne courbe côté entrées. Dans la norme européenne (CEI), utilisée dans beaucoup de manuels, toutes les portes sont des rectangles qui se distinguent par le signe inscrit à l'intérieur : & pour ET, ≥1 pour OU, =1 pour XOR et 1 pour NON.
| Porte | Nom en français | Symbole ANSI | Signe CEI | Expression booléenne | Quand la sortie vaut-elle 1 ? |
|---|---|---|---|---|---|
| AND | ET | Forme de D | & | Y = A · B | Les deux entrées valent 1 |
| OR | OU | Bouclier pointu | ≥1 | Y = A + B | Au moins une entrée vaut 1 |
| NOT | NON (inverseur) | Triangle + rond | 1 (rond en sortie) | Y = A' | L'entrée vaut 0 |
| NAND | NON-ET | Forme de D + rond | & (rond en sortie) | Y = (A · B)' | Au moins une entrée vaut 0 |
| NOR | NON-OU | Bouclier + rond | ≥1 (rond en sortie) | Y = (A + B)' | Les deux entrées valent 0 |
| XOR | OU exclusif | Bouclier à double courbe | =1 | Y = A ⊕ B | Les entrées sont différentes |
| XNOR | NON-OU exclusif | Double courbe + rond | =1 (rond en sortie) | Y = (A ⊕ B)' | Les entrées sont identiques |
Tables de vérité des portes logiques
Une table de vérité indique la sortie d'une porte pour chaque combinaison de ses entrées. Une porte à n entrées a 2ⁿ lignes : 4 lignes pour deux entrées, 8 pour trois et 16 pour quatre. Si tu écris les lignes dans l'ordre du comptage binaire (00, 01, 10, 11), tu n'oublieras aucune combinaison. Voici les six portes à deux entrées dans un seul tableau :
| A | B | ET | OU | NAND | NOR | XOR | XNOR |
|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 |
| 0 | 1 | 0 | 1 | 1 | 0 | 1 | 0 |
| 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
| 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |
Comme la porte NON n'a qu'une entrée, sa table compte deux lignes : quand A = 0 la sortie vaut 1, et quand A = 1 elle vaut 0. En regardant le tableau de près, tu remarques une logique : la colonne NAND est exactement l'inverse de ET, NOR l'inverse de OU et XNOR l'inverse de XOR. Pour les retenir, utilise ces règles courtes : ET demande "sont-elles toutes à 1 ?", OU "y en a-t-il au moins une à 1 ?" et XOR "les entrées sont-elles différentes ?" ; la porte dont le nom commence par N (ou NON) donne la réponse inverse à la même question. Pour essayer les portes toi-même et voir les symboles en direct, touche simplement les entrées A et B dans l'outil Portes logiques.
- ET : Deux interrupteurs en série. La lampe ne s'allume que si les deux sont fermés ; un coffre de banque qui s'ouvre avec deux clés différentes suit aussi la règle ET.
- OU : Deux boutons-poussoirs en parallèle. La même sonnette retentit, qu'on appuie sur le bouton de la porte d'entrée ou sur celui de la porte arrière.
- NON : La lampe du réfrigérateur. Porte fermée, l'interrupteur est enfoncé et la lampe éteinte ; quand la porte s'ouvre, l'interrupteur est relâché et la lampe s'allume.
- NAND : La règle "alerter si tout n'est pas en ordre". Si un seul des deux carters de sécurité d'une machine est ouvert, le voyant d'alarme s'allume.
- NOR : La règle "rien ne s'est produit". Un voyant vert "tout va bien" qui ne s'allume que si ni fumée ni gaz ne sont détectés.
- XOR : Le montage va-et-vient d'un escalier. Basculer l'interrupteur du bas ou celui du haut change l'état de la lampe ; elle est allumée quand les deux interrupteurs sont dans des positions différentes et éteinte quand ils sont identiques.
- XNOR : Un test d'égalité. Il donne 1 quand deux bits sont identiques ; on le trouve dans les comparateurs numériques et les circuits de détection d'erreurs.
Circuits intégrés de portes logiques : 74HC08, 74HC32, 74HC00
Plutôt que de construire les portes logiques transistor par transistor, on utilise des circuits intégrés tout faits. La famille la plus répandue en électronique de loisir est la série 74HC : un boîtier DIP à 14 broches contient quatre portes à deux entrées, l'alimentation va toujours sur la broche 14 (VCC) et la masse sur la broche 7 (GND). Les 74HC fonctionnent de 2 à 6 V, leurs entrées ne consomment presque aucun courant et, à 5 V, une porte a un temps de propagation d'environ 10 nanosecondes, des centaines de fois plus rapide qu'un simple digitalWrite sur Arduino. Chaque sortie garde ses niveaux de tension garantis sous une charge de 4 mA ; la limite absolue est de 25 mA par sortie et 50 mA pour tout le circuit.
| Circuit | Porte | Contenu | Brochage | Équivalent CMOS 4000 |
|---|---|---|---|---|
| 74HC08 | ET | 4 × 2 entrées | Standard (tableau ci-dessous) | CD4081 |
| 74HC32 | OU | 4 × 2 entrées | Standard | CD4071 |
| 74HC00 | NAND | 4 × 2 entrées | Standard | CD4011 |
| 74HC86 | XOR | 4 × 2 entrées | Standard | CD4070 |
| 74HC02 | NOR | 4 × 2 entrées | Différent : sorties sur 1, 4, 10, 13 | CD4001 |
| 74HC04 | NON | 6 × 1 entrée | Entrées sur 1, 3, 5, 9, 11, 13 | CD4069 |
| 74HC14 | NON (trigger de Schmitt) | 6 × 1 entrée | Identique au 74HC04 | CD40106 |
| CD4077 / 74HCS7266 | XNOR | 4 × 2 entrées | Rare ; en général 74HC86 + 74HC04 | CD4077 |
Les 74HC08, 74HC32, 74HC00 et 74HC86 ont exactement le même brochage ; seul le type de porte à l'intérieur change. L'encoche ou le point sur le dessus du boîtier repère la broche 1. En regardant le circuit de dessus, encoche à gauche, les broches sont numérotées dans le sens inverse des aiguilles d'une montre : la rangée du bas de gauche à droite de 1 à 7, la rangée du haut de droite à gauche de 8 à 14. A et B sont les entrées, Y la sortie, et le chiffre devant indique le numéro de la porte.
| Broche | Fonction | Broche | Fonction |
|---|---|---|---|
| 1 | 1A (entrée porte 1) | 14 | VCC (+2…6 V) |
| 2 | 1B (entrée porte 1) | 13 | 4B (entrée porte 4) |
| 3 | 1Y (sortie porte 1) | 12 | 4A (entrée porte 4) |
| 4 | 2A (entrée porte 2) | 11 | 4Y (sortie porte 4) |
| 5 | 2B (entrée porte 2) | 10 | 3B (entrée porte 3) |
| 6 | 2Y (sortie porte 2) | 9 | 3A (entrée porte 3) |
| 7 | GND | 8 | 3Y (sortie porte 3) |
Les circuits qui font le même travail existent en plusieurs familles. La série 74LS est l'ancienne technologie TTL : elle ne fonctionne qu'entre 4,75 et 5,25 V, consomme davantage et lit généralement une entrée en l'air comme un 1. La série 74HCT est un 74HC à entrées compatibles TTL ; elle s'alimente en 5 V mais reconnaît déjà 2 V comme un 1 certain, ce qui lui permet de lire sans problème les signaux 3,3 V d'un ESP32 ou d'un Pico. La série CD4000 (CD4081, CD4011, etc.) fonctionne sur une large plage de 3 à 18 V, mais elle est plus lente et son brochage diffère de celui des 74HC : un CD4011 ne remplace pas directement un 74HC00.
Expérience à boutons-poussoirs sur plaque d'essai : porte ET avec le 74HC08
Le meilleur moyen de comprendre une porte logique est de l'essayer toi-même avec deux boutons-poussoirs. Pas de microcontrôleur ici : il te faut seulement un 74HC08, deux boutons-poussoirs, deux résistances de 10 kΩ, une résistance de 1 kΩ, une LED et un condensateur de 100 nF. Pour l'alimentation, les broches 5V et GND d'un Arduino, un module d'alimentation pour plaque d'essai ou trois piles AA (4,5 V) suffisent. Si tu n'es pas sûr des connexions internes de la plaque d'essai, lis d'abord Qu'est-ce qu'une breadboard ?.

- Place le 74HC08 à cheval sur la rainure centrale de la plaque d'essai, les broches de part et d'autre, encoche vers la gauche.
- Relie la broche 14 à la ligne + (5 V) et la broche 7 à la ligne − (GND), puis place le condensateur de 100 nF entre ces deux broches.
- Relie un côté du bouton A à la ligne + et l'autre côté à la broche 1. Ajoute une résistance de 10 kΩ entre cette même broche et GND : cette résistance de pull-down (rappel au niveau bas) maintient l'entrée fermement à 0 tant que le bouton n'est pas enfoncé.
- Relie le bouton B à la broche 2 de la même façon et donne-lui aussi sa propre résistance de pull-down de 10 kΩ.
- Depuis la broche 3, la sortie, passe par une résistance de 1 kΩ jusqu'à la patte longue de la LED (anode) ; relie la patte courte (cathode) à GND.
- Relie à GND les entrées inutilisées, les broches 4, 5, 9, 10, 12 et 13 ; laisse libres les sorties 6, 8 et 11.
- Mets sous tension et essaie les quatre combinaisons l'une après l'autre : la LED ne doit s'allumer que lorsque tu appuies sur les deux boutons en même temps. Compare les résultats avec la table de vérité.
| Connexion | Broche du 74HC08 | À relier à |
|---|---|---|
| Alimentation | 14 (VCC) | Ligne +, 5 V |
| Masse | 7 (GND) | Ligne − |
| Condensateur de découplage | Entre 14 et 7 | 100 nF céramique, près du circuit |
| Entrée A | 1 | Bouton A → 5 V, 10 kΩ → GND |
| Entrée B | 2 | Bouton B → 5 V, 10 kΩ → GND |
| Sortie | 3 | 1 kΩ → anode de la LED, cathode → GND |
| Entrées inutilisées | 4, 5, 9, 10, 12, 13 | GND |
| Sorties inutilisées | 6, 8, 11 | Libres |
Construire toutes les portes avec des NAND : la porte universelle
La NAND est appelée porte universelle car on peut construire toutes les autres portes uniquement avec des NAND. Cela a aussi un intérêt pratique : en technologie CMOS, la NAND est l'une des portes les plus simples, avec seulement 4 transistors, alors qu'une porte ET est en réalité une NAND suivie d'une NON et en demande 6. Voilà pourquoi les concepteurs de puces adorent la NAND. La mémoire flash NAND des clés USB doit d'ailleurs son nom au fait que ses cellules sont reliées en série, comme les transistors d'une porte NAND. La NOR est elle aussi universelle : l'ordinateur de guidage d'Apollo, parti vers la Lune, était construit avec environ 2 800 circuits contenant chacun deux portes NOR à trois entrées.
| Porte à obtenir | Comment avec des NAND ? | NAND nécessaires |
|---|---|---|
| NON | A NAND A (relier les deux entrées) | 1 |
| ET | Faire passer la sortie de (A NAND B) dans une NON | 2 |
| OU | (A NAND A) NAND (B NAND B) | 3 |
| NOR | OU + NON | 4 |
| XOR | N1 = A NAND B ; (A NAND N1) NAND (B NAND N1) | 4 |
| XNOR | XOR + NON | 5 |
La ligne OU du tableau repose sur la loi de De Morgan : (A' · B')' = A + B. Autrement dit, si tu inverses d'abord chaque entrée puis que tu les envoies dans une NAND, tu obtiens un OU. La seconde loi de De Morgan s'écrit (A + B)' = A' · B'. Ces deux lois t'aident aussi à simplifier les conditions dans le code : sur Arduino, !(a && b) donne toujours le même résultat que (!a || !b), et !(a || b) le même que (!a && !b).
Construire un XOR avec quatre portes NAND est un exercice classique d'examen et de TP, et les quatre portes d'un seul 74HC00 suffisent exactement. On calcule d'abord N1 = A NAND B. Puis on obtient N2 = A NAND N1 et N3 = B NAND N1, et la sortie de la dernière porte, Y = N2 NAND N3, donne le XOR. Avec le câblage ci-dessous, tu transformes ton expérience sur plaque d'essai en un XOR à quatre NAND :
| Broche du 74HC00 | Connexion | Rôle |
|---|---|---|
| 1 et 4 | Bouton A | Entrée A (portes 1 et 2) |
| 2 et 10 | Bouton B | Entrée B (portes 1 et 3) |
| 3 → 5 et 9 | Fil | N1 = A NAND B |
| 6 → 12 | Fil | N2 = A NAND N1 |
| 8 → 13 | Fil | N3 = B NAND N1 |
| 11 | 1 kΩ + LED | Y = A XOR B |
| 14 / 7 | 5 V / GND | Alimentation |
Allons un peu plus loin : si tu relies en croix les sorties de deux portes NAND à l'entrée de l'autre, tu obtiens une mémoire de 1 bit appelée bascule RS (verrou SR). Ce circuit se souvient de son dernier état même quand tu relâches le bouton. Les registres des processeurs, les compteurs et des circuits comme le registre à décalage 74HC595 sont formés en enchaînant de telles cellules mémoire construites avec des portes.
Le demi-additionneur : additionner deux bits avec des portes
Ce que les portes logiques savent faire de plus impressionnant, c'est calculer. En binaire, 0 + 0 = 0, 0 + 1 = 1, 1 + 0 = 1 et 1 + 1 = 10 (2 en décimal). Le chiffre de droite du résultat s'appelle la somme et celui qui déborde vers la gauche la retenue (carry). En regardant le tableau ci-dessous, tu verras que la somme est exactement un XOR et la retenue exactement un ET. Une porte XOR et une porte ET côte à côte forment donc un demi-additionneur qui additionne deux nombres d'un bit.
| A | B | Retenue (C = A ET B) | Somme (S = A XOR B) | Résultat décimal |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 | 1 |
| 1 | 0 | 0 | 1 | 1 |
| 1 | 1 | 1 | 0 | 2 (binaire 10) |
Pour le monter sur la plaque d'essai, relie les boutons A et B aux broches 1 et 2 d'un 74HC86 et d'un 74HC08 à la fois. La broche 3 du 74HC86 commande la LED de somme, la broche 3 du 74HC08 la LED de retenue. Quand tu appuies sur les deux boutons, la LED de somme s'éteint et celle de retenue s'allume : les LED affichent le binaire 10, c'est-à-dire 2. Si tu veux n'utiliser qu'un 74HC00, il te faut quatre NAND pour le XOR et une cinquième NAND qui inverse N1 pour obtenir la retenue ; un demi-additionneur se construit donc avec 5 portes NAND.
Un demi-additionneur ne peut pas tenir compte de la retenue venant du rang inférieur ; pour cela, il faut un additionneur complet (full adder). Ses formules sont S = A ⊕ B ⊕ Cin et Cout = (A · B) + (Cin · (A ⊕ B)), soit deux demi-additionneurs et une porte OU. En chaînant quatre additionneurs complets pour que chacun transmette sa retenue au suivant, tu obtiens un additionneur 4 bits ; le circuit 74HC283 réalise la même addition 4 bits, mais calcule les retenues avec un circuit interne rapide (retenue anticipée, carry look-ahead) au lieu d'attendre qu'elles se propagent le long de la chaîne. L'unité arithmétique du processeur de ton ordinateur est une version 64 bits, bien plus rapide, de la même idée.
Les portes logiques sur Arduino : &&, ||, ! et opérations bit à bit
Dans le code Arduino, chaque porte logique a deux équivalents. Les opérateurs logiques (&&, ||, !) combinent des conditions et donnent un résultat true ou false ; tu les utilises dans les instructions if et while. Les opérateurs bit à bit (&, |, ^, ~) s'appliquent quant à eux à tous les bits d'un nombre en même temps, colonne par colonne ; travailler sur un octet revient à faire fonctionner huit portes à la fois. Les exemples du tableau utilisent les nombres 0b1100 et 0b1010 :
| Porte | Logique (bool) | Bit à bit | Exemple | Résultat |
|---|---|---|---|---|
| ET | a && b | x & y | 0b1100 & 0b1010 | 0b1000 |
| OU | a || b | x | y | 0b1100 | 0b1010 | 0b1110 |
| NON | !a | ~x | ~0b00001100 (byte) | 0b11110011 |
| NAND | !(a && b) | ~(x & y) | ~(0b1100 & 0b1010) & 0x0F | 0b0111 |
| NOR | !(a || b) | ~(x | y) | ~(0b1100 | 0b1010) & 0x0F | 0b0001 |
| XOR | a != b | x ^ y | 0b1100 ^ 0b1010 | 0b0110 |
| XNOR | a == b | ~(x ^ y) | ~(0b1100 ^ 0b1010) & 0x0F | 0b1001 |
La différence entre les deux familles semble mince, mais elle provoque des bugs sournois. && et || utilisent l'évaluation en court-circuit : dans a && b, si a est faux, b n'est même pas évalué. & évalue toujours les deux côtés et regarde les bits des nombres : 2 && 1 vaut true, mais 2 & 1 vaut 0, car 0b10 et 0b01 n'ont aucun bit en commun. Le C++ n'a pas d'opérateur XOR logique à part ; pour deux bool, écrire a != b est le plus lisible. Pour aller plus loin sur les opérations bit à bit, les décalages << et >> et le système binaire, consulte Systèmes de numération et opérations bit à bit.
Passons maintenant l'expérience de la plaque d'essai sur un Arduino Uno. Deux boutons-poussoirs vont sur les broches 2 et 3, et sept LED (chacune avec une résistance de 330 Ω) sur les broches 4 à 10. Chaque bouton a un côté sur la broche et l'autre sur GND ; comme la résistance de pull-up interne est activée, aucune résistance supplémentaire n'est nécessaire. Un seul programme fait vivre les sept portes en même temps :
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}Avec INPUT_PULLUP, un bouton enfoncé se lit LOW ; le code inverse donc la lecture avec ! et un bouton enfoncé devient 1. Chaque LED affiche ensuite le résultat de sa porte : 4 ET, 5 OU, 6 NON A, 7 NAND, 8 NOR, 9 XOR et 10 XNOR. Si tu ouvres le moniteur série à 9600 bauds, la ligne complète s'affiche à chaque changement de bouton ; après avoir essayé les quatre combinaisons, tu auras établi la table de vérité de tes propres mains. Les détails de la logique pull-up sont dans Comment brancher un bouton-poussoir sur Arduino.
Pour voir la puissance des opérations bit à bit, le deuxième exemple calcule toute la table de vérité en quelques lignes. L'astuce : si tu écris la colonne A sous la forme du nombre 0b1100 et la colonne B sous la forme 0b1010, chaque bit correspond à une ligne du tableau, et un seul & te donne d'un coup les quatre lignes de la colonne ET. La seconde moitié du programme additionne bit à bit deux nombres de 4 bits avec les formules de l'additionneur complet, imitant ainsi en logiciel le circuit additionneur d'un processeur. Ce programme ne demande aucun matériel ; ouvre simplement le moniteur série.
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}Un testeur de circuits 74HC avec Arduino
Si le marquage d'un circuit est effacé ou si tu veux savoir s'il fonctionne encore, tu peux transformer l'Arduino en testeur. Ce programme applique tour à tour les quatre combinaisons d'entrée aux quatre portes d'un 74HC00, 74HC08, 74HC32 ou 74HC86 (les circuits au brochage standard), lit les sorties et compare le résultat à des motifs connus. Relie la broche 14 du circuit au 5V, la broche 7 à GND et les autres broches aux broches de l'Arduino indiquées dans le tableau du code.
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}Une porte logique programmable avec l'ESP32
Sur l'ESP32, les mêmes opérateurs fonctionnent sans changement. Dans cet exemple, un troisième bouton fait défiler les types de portes et une seule LED affiche la sortie de la porte choisie. Tu peux ainsi montrer six portes avec un seul circuit en classe ou lors d'une présentation. Les boutons vont sur GPIO 25, 26 et 27 (leur autre côté sur GND) et la LED sur GPIO 23 à travers une résistance de 220 Ω ; le nom de la porte choisie s'affiche dans le moniteur série à 115200 bauds.
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}Portes logiques avec le Raspberry Pi Pico et MicroPython
En MicroPython, les opérateurs logiques s'écrivent avec des mots anglais : and, or, not. Les opérateurs bit à bit sont les mêmes qu'en C++ : &, |, ^ et ~. Le code ci-dessous lit deux boutons-poussoirs sur GP14 et GP15 et affiche les résultats de ET, OU, NAND, NOR, XOR et XNOR sur six LED reliées à GP16–GP21. L'autre côté de chaque bouton va à GND et chaque LED est reliée par une résistance de 220 à 330 Ω. Si tu enregistres le code dans Thonny sous le nom main.py, il s'exécute à chaque mise sous tension du Pico ; si tu débutes avec le Pico, commence par Qu'est-ce que le Raspberry Pi Pico ?.
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)Python cache un piège semblable : ~True donne -2, car un bool est en réalité un entier. Pour inverser un bit, utilise not x, 1 - x ou x ^ 1. De plus, les opérateurs and et or de Python ne renvoient pas toujours True ou False, mais la dernière valeur évaluée : 0 or 5 donne 5. C'est pourquoi le code utilise des conversions int(), afin que les LED ne reçoivent jamais autre chose que 0 ou 1.
Idées de projets avec des portes logiques
- Veilleuse intelligente (ET) : Allume la lumière quand il fait sombre ET qu'un mouvement est détecté ; combine une photorésistance LDR et un capteur PIR dans une seule condition &&.
- Éclairage d'escalier (XOR) : Commande une lampe avec deux boutons en bas et en haut de l'escalier ; calcule l'état de la lampe avec un XOR et commute la lampe 230 V avec un module relais.
- Alarme maison (ET + OU) : Quand le système est armé, déclenche la sirène si la porte OU la fenêtre s'ouvre. Détecte la porte et la fenêtre avec un interrupteur reed ; les détails sont dans le guide système d'alarme Arduino.
- Coffre à deux clés (ET) : La serrure ne s'ouvre que si deux personnes différentes appuient en même temps sur leur bouton, ou une fois le code du clavier matriciel validé.
- Calculatrice 4 bits : Additionne deux nombres saisis avec des interrupteurs grâce à la logique de l'additionneur complet et affiche le résultat sur un afficheur 7 segments.
- Buzzer de quiz : Verrouille la LED du premier candidat qui appuie et bloque les autres ; c'est la version logicielle d'une bascule à base de NAND.
- Contrôle de parité : Combine tous les bits d'un octet avec XOR ; si le résultat vaut 1, le nombre de 1 est impair. Le bit de parité des liaisons série est calculé exactement de cette façon.
Erreurs fréquentes et solutions
| Symptôme | Cause probable | Solution |
|---|---|---|
| La LED clignote toute seule et change quand tu approches la main | Entrée flottante, pas de résistance de pull-down | Ajoute une résistance de pull-down ou pull-up de 10 kΩ sur chaque entrée |
| Le circuit chauffe | VCC et GND inversés ou deux sorties reliées | La broche 14 va au VCC et la 7 à GND ; ne relie jamais des sorties |
| Aucune porte ne réagit | Pas d'alimentation ou circuit mal placé sur la rainure | Mesure entre les broches 14 et 7 au multimètre, place le circuit à cheval sur la rainure |
| Résultats faux avec un 74HC02 ou un CD4011 | Brochage différent de celui du 74HC08 | Câble selon le tableau des broches de la fiche technique |
| Le circuit consomme plus que prévu | Entrées inutilisées en l'air | Relie toutes les entrées libres à GND |
| Résultats instables avec un ESP32 ou un Pico | Un signal 3,3 V ne suffit pas pour un 74HC en 5 V | Alimente le 74HC en 3,3 V ou utilise un 74HCT |
| if (a & b) est faux de façon inattendue | & travaille bit à bit ; 2 & 1 = 0 | Utilise && dans les conditions |
| if (x & 1 == 0) ne s'exécute jamais | == est évalué avant & | Ajoute des parenthèses : (x & 1) == 0 |
| Un appui change la porte plusieurs fois | Rebonds du bouton | Attends 20 à 50 ms en logiciel ou utilise un filtre RC + 74HC14 |
Les portes logiques sont l'alphabet de tout le monde numérique, de l'allumage d'une LED jusqu'à l'addition dans un processeur. Une fois que tu maîtrises ET, OU et NON, lire une condition if, une règle d'alarme ou un registre à décalage devient beaucoup plus simple. Dans l'application BlueGrays, tu trouveras des projets pour allumer une LED avec un bouton, des projets à boutons pour ESP32 et Raspberry Pi Pico, un éclairage d'escalier intelligent et un éclairage intelligent qui combine PIR et LDR, chacun avec schémas et code pas à pas, pour mettre en pratique dans de vrais projets la logique des portes vue dans cet article.
Questions fréquentes
Quelles sont les portes logiques et à quoi servent-elles ?
Il existe sept portes logiques de base : ET, OU, NON, NAND (NON-ET), NOR (NON-OU), XOR (OU exclusif) et XNOR. Chacune observe des entrées valant 0 ou 1 et produit une seule sortie selon sa propre règle. Tous les circuits numériques, comme les processeurs, les mémoires, les compteurs et les calculatrices, sont formés en combinant ces portes.
Comment faire une table de vérité ?
Détermine d'abord le nombre de lignes à partir du nombre d'entrées : n entrées demandent 2ⁿ lignes. Écris les entrées dans l'ordre du comptage binaire (00, 01, 10, 11), puis applique la règle de la porte à chaque ligne pour remplir la colonne de sortie. Pour un circuit à plusieurs portes, ajouter une colonne par sortie intermédiaire facilite le calcul.
Pourquoi la porte NAND est-elle universelle ?
Parce qu'avec uniquement des portes NAND, tu peux construire NON, ET, OU, NOR, XOR et XNOR. Par exemple, relier les deux entrées d'une NAND donne un NON, deux NAND à la suite donnent un ET et quatre NAND donnent un XOR. La porte NOR possède la même propriété et est donc elle aussi universelle.
Quelle est la différence entre XOR et XNOR ?
XOR donne 1 quand les entrées sont différentes, alors que XNOR donne 1 quand elles sont identiques. XNOR est l'inverse de XOR et sert à vérifier si deux bits sont égaux. XOR est utilisé dans les additionneurs, le contrôle de parité et pour inverser un bit.
Quelle est la différence entre le 74HC08 et le 74LS08 ?
Les deux contiennent quatre portes ET à deux entrées et ont le même brochage. Le 74HC08 est en technologie CMOS, fonctionne de 2 à 6 V et consomme très peu ; le 74LS08 est en TTL, ne fonctionne qu'autour de 5 V et consomme davantage. Pour un nouveau projet, choisis le 74HC, et le 74HCT pour relier des signaux 3,3 V à un circuit 5 V.
Quelle est la différence entre && et & sur Arduino ?
&& est l'opérateur ET logique : il vérifie si les deux conditions sont vraies et renvoie true ou false. & est le ET bit à bit et compare séparément chaque bit de deux nombres. C'est pourquoi 2 && 1 vaut true mais 2 & 1 vaut 0 ; dans les conditions if, utilise &&.
Projets à réaliser après cet article
Voir tous les projets
Allumer une LED avec un bouton-poussoir (Push)
Comme une sonnette : la lumière reste allumée tant que tu appuies et s'éteint quand tu relâches. L'Arduino surveille le bouton en permanence ; tant qu'il est enfoncé la LED est allumée, et dès que tu

Allumer et éteindre une LED avec un bouton
Un appui et la lumière s'allume, un deuxième et elle s'éteint, exactement comme l'interrupteur de ta chambre. L'Arduino remarque chaque appui et fait passer la LED à l'état inverse, en attendant un co

ESP32 Contrôle de LED avec bouton poussoir (Push)
La LED s'allume lorsque le bouton est enfoncé et s'éteint lorsqu'il est relâché. Montre comment la broche d'entrée numérique de l'ESP32 et la résistance pull-up interne sont utilisées. Grâce au mode INPUT_PULLUP, aucune résistance externe n'est nécessaire.

ESP32 Contrôle de LED avec bouton (Toggle)
Chaque fois que l'on appuie sur le bouton, la LED change d'état : si elle est allumée, elle s'éteint, si elle est éteinte, elle s'allume. Modèle classique de basculement. Avec le debounce, nous nettoyons le bruit mécanique du bouton-poussoir pour garantir un seul basculement avec une seule pression.

Raspberry Pi Pico LED Contrôlée par Bouton (Push, GP14 + GP2)
Premier projet **entrée** avec Pico — lecture bouton ! 🔘 LED s'allume tant que le bouton est pressé. Apprends `Pin.IN`, `Pin.PULL_UP` et `button.value()`. GP14 LED, GP2 bouton avec PULL_UP interne. Pressé = 0, relâché = 1 — standard.

Raspberry Pi Pico : commande indépendante de 2 LED à l'aide de 2 boutons (GP12-13 + GP4-5)
2 boutons, 2 LED — totalement indépendants l'un de l'autre ! 🔴🟢 Chaque bouton contrôle sa propre LED : lorsque BTN1 est enfoncé, la LED rouge s'allume ; lorsque BTN2 est enfoncé, la LED verte s'allume. Si vous appuyez sur les deux en même temps, les deux LED s'allument (fonctionnement en parallèle). Apprentissage : **gestion d'objets à broches multiples** (plusieurs entrées/sorties simultanées), **opérateur ternaire** (`1 if x else 0` — l'if-else compact de Python), **contrôle indépendant des E/

Éclairage intelligent des escaliers et des couloirs
Pose le pied dans l'escalier ou le couloir et les lumières s'allument marche après marche dans ton sens de passage. Un capteur de distance se trouve à chaque extrémité ; quel que soit celui devant leq

Éclairage Intelligent ESP32 (PIR + LDR + Relais + OLED)
Transformez votre couloir, votre salle de bain ou votre garde-manger en éclairage intelligent avec l'ESP32 ! En utilisant un capteur de mouvement PIR, un capteur de lumière LDR et un module relais, nous construisons le scénario classique "la lumière s'allume lorsqu'un mouvement est détecté dans l'obscurité" — si l'environnement est déjà lumineux, le mouvement N'ACTIVE PAS la lumière, économisant ainsi de l'énergie pendant la journée. La lumière reste allumée pendant 30 secondes ; si le mouvement
Autres articles
Application BlueGrays
Réalise ce montage pas à pas sur ton téléphone
Schéma, code et liste des composants sur un seul écran. Plus de 160 projets Arduino, ESP32 et Pico à réaliser.
Scanne avec ton téléphone
Pointe l’appareil photo vers le code : la boutique d’applications de ton téléphone s’ouvre.
ou ouvre la boutique

