Логические элементы: таблицы истинности AND, OR, NOT, XOR и Arduino
Что такое логические элементы? Обозначения AND, OR, NOT, NAND, NOR, XOR и XNOR, таблицы истинности, микросхемы 74HC08 и 74HC00, полусумматор и код для Arduino, ESP32 и Pico.
Логические элементы — базовые кирпичики цифровых схем: каждый смотрит на один или несколько цифровых входов и по фиксированному правилу выдаёт один цифровой выход. Входы могут быть только 0 (LOW) или 1 (HIGH), и выход тоже. Базовых элементов семь: AND, OR, NOT, NAND, NOR, XOR и XNOR (И, ИЛИ, НЕ, И-НЕ, ИЛИ-НЕ, исключающее ИЛИ и исключающее ИЛИ-НЕ). От процессора в твоём телефоне до платы управления стиральной машиной, от ATmega328P внутри Arduino до карманного калькулятора — любое цифровое устройство работает, соединяя миллионы крошечных логических элементов.
В этом руководстве ты узнаешь обозначение и таблицу истинности каждого элемента, настоящие микросхемы вроде 74HC08, 74HC32 и 74HC00, опыт на макетной плате с двумя кнопками, как собрать любой другой элемент только из NAND, и схему полусумматора, складывающую два бита. В последних разделах превратим ту же логику в код на Arduino с операторами &&, || и ! и побитовыми операциями, а затем продолжим примерами для ESP32 и Raspberry Pi Pico (MicroPython).

Что такое логический элемент и как он работает?
В цифровой электронике каждый сигнал находится в одном из двух состояний: 1 (HIGH, истина) или 0 (LOW, ложь). Математика работы с этими двумя значениями называется булевой алгеброй; в книге, вышедшей в 1854 году, Джордж Буль именно так выразил логические рассуждения в виде алгебры. В 1937 году Клод Шеннон показал, что эта алгебра один в один ложится на переключательные схемы из реле, заложив основу проектирования цифровых схем. Сегодня логический элемент содержит всего несколько транзисторов: в технологии CMOS элемент NOT состоит из 2 MOSFET, а NAND — из 4. Как транзистор работает ключом, объясняем в статье Что такое транзистор?
Так какое напряжение схема считает 1, а какое 0? Это зависит от напряжения питания платы и семейства микросхем. Таблица ниже показывает границы, при которых вход гарантированно считается 1 или 0. Область между двумя границами — неопределённая зона; если вход остаётся в ней, выход может вести себя случайно. Вход, ни к чему не подключённый, то есть висящий (floating), блуждает как раз в этой неопределённой зоне. Поэтому каждый вход нужно подключить к сигналу или через резистор к GND или VCC.
| Плата / семейство | Питание | Вход гарантированно 1 | Вход гарантированно 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 |
| Микросхема 74HC | 5 V | ≥ 3,5 V | ≤ 1,5 V |
| Микросхема 74HCT | 5 V | ≥ 2,0 V | ≤ 0,8 V |
| Микросхема CD4000 | 5 V | ≥ 3,5 V | ≤ 1,5 V |
7 базовых логических элементов и их обозначения
На схемах элементы рисуют по двум разным стандартам. В американском стандарте (ANSI/IEEE) у каждого элемента своя форма: AND похож на букву D, OR — на заострённый щит, а NOT — на треугольник. Маленький кружок (bubble) на выходе означает «инвертировать»; NAND — это, по сути, AND с кружком на конце. От OR элемент XOR отличает вторая изогнутая линия со стороны входов. В европейском стандарте (IEC), принятом и в российских схемах, все элементы — прямоугольники, различающиеся знаком внутри: & для AND, ≥1 для OR, =1 для XOR и 1 для NOT. В учебниках встретятся и названия И-НЕ для NAND, ИЛИ-НЕ для NOR, исключающее ИЛИ для XOR и исключающее ИЛИ-НЕ для XNOR.
| Элемент | Другое название | Обозначение ANSI | Знак IEC | Булево выражение | Когда выход 1? |
|---|---|---|---|---|---|
| AND | Конъюнкция (И) | Форма D | & | Y = A · B | Оба входа 1 |
| OR | Дизъюнкция (ИЛИ) | Заострённый щит | ≥1 | Y = A + B | Хотя бы один вход 1 |
| NOT | Инвертор (НЕ) | Треугольник + кружок | 1 (кружок на выходе) | Y = A' | Вход 0 |
| NAND | И-НЕ | Форма D + кружок | & (кружок на выходе) | Y = (A · B)' | Хотя бы один вход 0 |
| NOR | ИЛИ-НЕ | Щит + кружок | ≥1 (кружок на выходе) | Y = (A + B)' | Оба входа 0 |
| XOR | Исключающее ИЛИ | Щит с двойной дугой | =1 | Y = A ⊕ B | Входы различаются |
| XNOR | Исключающее ИЛИ-НЕ | Двойная дуга + кружок | =1 (кружок на выходе) | Y = (A ⊕ B)' | Входы равны |
Таблицы истинности логических элементов
Таблица истинности перечисляет выход элемента для каждой комбинации входов. У элемента с n входами 2ⁿ строк: 4 строки для двух входов, 8 для трёх и 16 для четырёх. Если записывать строки в порядке двоичного счёта (00, 01, 10, 11), ни одна комбинация не потеряется. Вот все шесть двухвходовых элементов в одной таблице:
| A | B | AND | OR | 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 |
У элемента NOT один вход, поэтому в его таблице две строки: при A = 0 выход 1, при A = 1 выход 0. Присмотрись к таблице, и увидишь закономерность: столбец NAND в точности противоположен AND, NOR — OR, а XNOR — XOR. Чтобы запомнить, используй короткие правила: AND спрашивает «все ли равны 1?», OR — «есть ли хотя бы одна 1?», XOR — «различаются ли входы?»; элемент, чьё название начинается с N, даёт на тот же вопрос противоположный ответ. Чтобы самому попробовать элементы и увидеть обозначения вживую, просто нажимай на входы A и B в утилите «Логические элементы».
- AND: два выключателя последовательно. Лампа горит, только когда замкнуты оба; банковское хранилище, открывающееся двумя разными ключами, тоже следует правилу AND.
- OR: две кнопки параллельно. Один и тот же звонок звенит, нажмёт ли кто-то кнопку у парадной двери или у задней.
- NOT: свет в холодильнике. Пока дверь закрыта, выключатель прижат, и лампа не горит; когда дверь открывается, выключатель отпускается, и лампа загорается.
- NAND: правило «предупреждай, если не всё в порядке». Если открыт хотя бы один из двух защитных кожухов станка, загорается предупреждающая лампа.
- NOR: правило «ничего не случилось». Зелёная лампа «всё в порядке», которая горит, только когда не обнаружены ни дым, ни газ.
- XOR: проходные выключатели на лестнице. Переключение нижнего или верхнего выключателя меняет состояние лампы; лампа горит, когда выключатели в разных положениях, и не горит, когда в одинаковых.
- XNOR: проверка на равенство. Выдаёт 1, когда два бита одинаковы; используется в цифровых компараторах и схемах проверки ошибок.
Микросхемы логических элементов: 74HC08, 74HC32, 74HC00
Вместо того чтобы собирать логические элементы из отдельных транзисторов, используют готовые микросхемы. Самое распространённое семейство в любительской электронике — серия 74HC: в 14-выводном корпусе DIP четыре двухвходовых элемента, питание всегда подаётся на вывод 14 (VCC), а земля — на вывод 7 (GND). Микросхемы 74HC работают от 2 до 6 V, их входы почти не потребляют ток, а при 5 V задержка одного элемента около 10 наносекунд — в сотни раз быстрее одного вызова digitalWrite на Arduino. Каждый выход держит гарантированные уровни напряжения при нагрузке 4 mA; абсолютный предел — 25 mA на выход и 50 mA на всю микросхему.
| Микросхема | Элемент | Содержит | Распиновка | Аналог CMOS 4000 |
|---|---|---|---|---|
| 74HC08 | AND | 4 × 2 входа | Стандартная (таблица ниже) | CD4081 |
| 74HC32 | OR | 4 × 2 входа | Стандартная | CD4071 |
| 74HC00 | NAND | 4 × 2 входа | Стандартная | CD4011 |
| 74HC86 | XOR | 4 × 2 входа | Стандартная | CD4070 |
| 74HC02 | NOR | 4 × 2 входа | Другая: выходы на 1, 4, 10, 13 | CD4001 |
| 74HC04 | NOT | 6 × 1 вход | Входы на 1, 3, 5, 9, 11, 13 | CD4069 |
| 74HC14 | NOT (триггер Шмитта) | 6 × 1 вход | Как у 74HC04 | CD40106 |
| CD4077 / 74HCS7266 | XNOR | 4 × 2 входа | Трудно найти; обычно 74HC86 + 74HC04 | CD4077 |
У 74HC08, 74HC32, 74HC00 и 74HC86 в точности одинаковая распиновка; меняется только тип элементов внутри. Выемка или точка сверху на микросхеме отмечает вывод 1. Если смотреть на микросхему сверху выемкой влево, выводы нумеруются против часовой стрелки: нижний ряд идёт 1–7 слева направо, а верхний — 8–14 справа налево. A и B — входы, Y — выход, а цифра впереди — номер элемента.
| Вывод | Назначение | Вывод | Назначение |
|---|---|---|---|
| 1 | 1A (вход элемента 1) | 14 | VCC (+2…6 V) |
| 2 | 1B (вход элемента 1) | 13 | 4B (вход элемента 4) |
| 3 | 1Y (выход элемента 1) | 12 | 4A (вход элемента 4) |
| 4 | 2A (вход элемента 2) | 11 | 4Y (выход элемента 4) |
| 5 | 2B (вход элемента 2) | 10 | 3B (вход элемента 3) |
| 6 | 2Y (выход элемента 2) | 9 | 3A (вход элемента 3) |
| 7 | GND | 8 | 3Y (выход элемента 3) |
Микросхемы, выполняющие одну и ту же работу, бывают разных семейств. Серия 74LS — более старая технология TTL: она работает только от 4,75–5,25 V, потребляет больше тока и обычно читает висящий вход как 1. Серия 74HCT — это 74HC с входами, совместимыми с TTL; она питается от 5 V, но гарантированно принимает за 1 всё от 2 V, поэтому без проблем читает сигналы 3,3 V от ESP32 или Pico. Серия CD4000 (CD4081, CD4011 и так далее) работает в широком диапазоне 3–18 V, но медленнее, а её распиновка отличается от 74HC: CD4011 нельзя просто поставить вместо 74HC00.
Опыт на макетной плате с кнопками: элемент AND на 74HC08
Лучший способ понять логический элемент — самому попробовать его с двумя кнопками. В этом опыте нет микроконтроллера; нужны только 74HC08, две кнопки, два резистора 10 kΩ, резистор 1 kΩ, светодиод и конденсатор 100 nF. Для питания подойдут пины 5V и GND у Arduino, модуль питания макетной платы или три батарейки AA (4,5 V). Если непонятно, как макетная плата соединена внутри, сначала прочитай Что такое макетная плата?

- Поставь 74HC08 поперёк выемки посередине макетной платы, чтобы выводы оказались по обе стороны, выемкой влево.
- Подключи вывод 14 к шине + (5 V), а вывод 7 — к шине − (GND) и поставь между этими выводами конденсатор 100 nF.
- Одну сторону кнопки A подключи к шине +, а другую — к выводу 1. С того же вывода добавь резистор 10 kΩ на GND: этот стягивающий (pull-down) резистор надёжно держит вход в 0, пока кнопка не нажата.
- Так же подключи кнопку B к выводу 2 и дай ей свой стягивающий резистор 10 kΩ.
- От вывода 3, выхода, проведи через резистор 1 kΩ к длинной ножке (аноду) светодиода; короткую ножку (катод) подключи к GND.
- Неиспользуемые входы, выводы 4, 5, 9, 10, 12 и 13, соедини с GND; выходы 6, 8 и 11 оставь свободными.
- Подай питание и по очереди попробуй четыре комбинации: светодиод должен гореть, только когда обе кнопки нажаты вместе. Сравни результаты с таблицей истинности.
| Подключение | Вывод 74HC08 | Куда подключать |
|---|---|---|
| Питание | 14 (VCC) | Шина +, 5 V |
| Земля | 7 (GND) | Шина − |
| Развязывающий конденсатор | Между 14 и 7 | Керамический 100 nF, рядом с микросхемой |
| Вход A | 1 | Кнопка A → 5 V, 10 kΩ → GND |
| Вход B | 2 | Кнопка B → 5 V, 10 kΩ → GND |
| Выход | 3 | 1 kΩ → анод светодиода, катод светодиода → GND |
| Неиспользуемые входы | 4, 5, 9, 10, 12, 13 | GND |
| Неиспользуемые выходы | 6, 8, 11 | Свободны |
Любой элемент из NAND: универсальный элемент
NAND называют универсальным элементом, потому что из одних только элементов NAND можно собрать любой другой. У этого есть и практическая сторона: в технологии CMOS NAND — один из самых простых элементов, ему нужно всего 4 транзистора, а AND — это на самом деле NAND с NOT после него, и ему нужно 6. Поэтому разработчики микросхем так любят NAND. Флеш-память NAND в USB-флешках тоже названа так из-за того, что её ячейки соединены последовательно, как транзисторы в элементе NAND. NOR тоже универсален: бортовой компьютер «Аполлона» (Apollo Guidance Computer), летавшего на Луну, был собран примерно из 2800 микросхем, в каждой из которых два трёхвходовых элемента NOR.
| Какой элемент собрать | Как из NAND? | Нужно NAND |
|---|---|---|
| NOT | A NAND A (соедини оба входа вместе) | 1 |
| AND | Пропусти выход (A NAND B) через NOT | 2 |
| OR | (A NAND A) NAND (B NAND B) | 3 |
| NOR | OR + NOT | 4 |
| XOR | N1 = A NAND B; (A NAND N1) NAND (B NAND N1) | 4 |
| XNOR | XOR + NOT | 5 |
Строка OR в таблице опирается на закон де Моргана: (A' · B')' = A + B. Иначе говоря, если сначала инвертировать оба входа, а потом подать их на NAND, получится OR. Второй закон де Моргана: (A + B)' = A' · B'. Оба закона помогают упрощать условия и в коде: на Arduino !(a && b) всегда даёт тот же результат, что (!a || !b), а !(a || b) — то же, что (!a && !b).
Сборка XOR из четырёх элементов NAND — классическое экзаменационное и лабораторное упражнение, и четырёх элементов одной 74HC00 ровно хватает. Сначала вычисляется N1 = A NAND B. Затем находятся N2 = A NAND N1 и N3 = B NAND N1, а выход последнего элемента, Y = N2 NAND N3, даёт XOR. С подключением ниже опыт на макетной плате превращается в XOR на четырёх NAND:
| Вывод 74HC00 | Подключение | Роль |
|---|---|---|
| 1 и 4 | Кнопка A | Вход A (элементы 1 и 2) |
| 2 и 10 | Кнопка B | Вход B (элементы 1 и 3) |
| 3 → 5 и 9 | Перемычка | N1 = A NAND B |
| 6 → 12 | Перемычка | N2 = A NAND N1 |
| 8 → 13 | Перемычка | N3 = B NAND N1 |
| 11 | 1 kΩ + светодиод | Y = A XOR B |
| 14 / 7 | 5 V / GND | Питание |
Пойдём на шаг дальше: если перекрёстно соединить выходы двух элементов NAND со входами друг друга, получится 1-битная память — RS-защёлка (SR latch). Эта схема помнит последнее состояние даже после того, как отпустишь кнопку. Регистры в процессорах, счётчики и микросхемы вроде сдвигового регистра 74HC595 сделаны из таких ячеек памяти на элементах, соединённых цепочкой.
Полусумматор: складываем два бита элементами
Самое впечатляющее, что умеют логические элементы, — складывать числа. В двоичной системе 0 + 0 = 0, 0 + 1 = 1, 1 + 0 = 1 и 1 + 1 = 10 (2 в десятичной). Правая цифра результата называется суммой, а цифра, переходящая влево, — переносом. Из таблицы ниже видно, что сумма — это в точности XOR, а перенос — в точности AND. Значит, элементы XOR и AND рядом образуют полусумматор, складывающий два однобитных числа.
| A | B | Перенос (C = A AND B) | Сумма (S = A XOR B) | Десятичный результат |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 | 1 |
| 1 | 0 | 0 | 1 | 1 |
| 1 | 1 | 1 | 0 | 2 (двоичное 10) |
Чтобы собрать его на макетной плате, подключи кнопки A и B к выводам 1 и 2 и 74HC86, и 74HC08. Вывод 3 микросхемы 74HC86 управляет светодиодом суммы, а вывод 3 микросхемы 74HC08 — светодиодом переноса. Когда нажимаешь обе кнопки, светодиод суммы гаснет, а светодиод переноса загорается: светодиоды показывают двоичное 10, то есть 2. Если хочешь обойтись только 74HC00, нужны четыре NAND для XOR и пятый NAND, инвертирующий N1, чтобы получить перенос; иначе говоря, полусумматору нужно 5 элементов NAND.
Полусумматор не может учесть перенос, пришедший из младшего разряда; для этого нужен полный сумматор. Его формулы: S = A ⊕ B ⊕ Cin и Cout = (A · B) + (Cin · (A ⊕ B)), то есть два полусумматора плюс элемент OR. Соедини четыре полных сумматора так, чтобы каждый передавал перенос следующему, и получится 4-битный сумматор; готовая микросхема 74HC283 делает то же 4-битное сложение, но вычисляет переносы быстрой внутренней схемой (ускоренный перенос, carry look-ahead), а не ждёт, пока они пробегут по цепочке. Арифметический блок процессора в твоём компьютере — 64-битная и гораздо более быстрая версия той же идеи.
Логические элементы на Arduino: &&, ||, ! и побитовые операции
В коде Arduino у каждого логического элемента два аналога. Логические операторы (&&, ||, !) объединяют условия и дают результат true или false; их используют в if и while. Побитовые операторы (&, |, ^, ~) применяются сразу ко всем битам числа, столбец за столбцом; работа с байтом — как восемь элементов одновременно. В примерах таблицы используются числа 0b1100 и 0b1010:
| Элемент | Логический (bool) | Побитовый | Пример | Результат |
|---|---|---|---|---|
| AND | a && b | x & y | 0b1100 & 0b1010 | 0b1000 |
| OR | a || b | x | y | 0b1100 | 0b1010 | 0b1110 |
| NOT | !a | ~x | ~0b00001100 (байт) | 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 |
Разница между двумя видами кажется маленькой, но порождает коварные ошибки. && и || вычисляются по короткой схеме: в a && b, если a ложно, b вообще не вычисляется. & всегда вычисляет обе стороны и смотрит на биты чисел: 2 && 1 — истина, а 2 & 1 — это 0, ведь у 0b10 и 0b01 нет общих битов. Отдельного логического оператора XOR в C++ нет; для двух bool понятнее всего написать a != b. Подробнее о побитовых операциях, сдвигах << и >> и двоичной системе — в статье Системы счисления и побитовые операции.
Теперь перенесём опыт с макетной платы на Arduino Uno. Две кнопки идут на пины 2 и 3, а семь светодиодов (каждый с резистором 330 Ω) — на пины 4–10. Одна сторона каждой кнопки идёт на пин, другая — на GND; поскольку включена встроенная подтяжка, дополнительный резистор не нужен. Один скетч оживляет сразу все семь элементов:
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}С INPUT_PULLUP нажатая кнопка читается как LOW, поэтому код инвертирует показание через !, и нажатая кнопка становится 1. Каждый светодиод затем показывает результат своего элемента: 4 AND, 5 OR, 6 NOT A, 7 NAND, 8 NOR, 9 XOR и 10 XNOR. Если открыть монитор порта на скорости 9600 бод, при каждом изменении кнопки выводится вся строка; попробовав все четыре комбинации, ты своими руками получишь таблицу истинности. Подробности о подтяжке — в статье Как подключить кнопку к Arduino.
Чтобы увидеть силу побитовых операций, второй пример вычисляет всю таблицу истинности в несколько строк. Хитрость: если записать столбец A числом 0b1100, а столбец B — числом 0b1010, каждый бит соответствует одной строке таблицы, и один & сразу даёт все четыре строки столбца AND. Вторая половина скетча побитно складывает два 4-битных числа по формулам полного сумматора, программно имитируя схему сумматора процессора. Этому скетчу оборудование не нужно; просто открой монитор порта.
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}Тестер микросхем 74HC на Arduino
Если маркировка на микросхеме стёрлась или хочется узнать, жива ли она, Arduino можно превратить в тестер. Этот скетч по очереди подаёт четыре комбинации входов на все четыре элемента 74HC00, 74HC08, 74HC32 или 74HC86 (микросхем со стандартной распиновкой), читает выходы и сравнивает результат с известными шаблонами. Подключи вывод 14 микросхемы к 5V, вывод 7 к GND, а остальные выводы — к пинам Arduino из таблицы в коде.
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}Программируемый логический элемент на ESP32
Те же операторы без изменений работают на ESP32. В этом примере третья кнопка перебирает типы элементов, а один светодиод показывает выход выбранного элемента. Так одной схемой можно продемонстрировать шесть элементов на уроке или презентации. Кнопки идут на GPIO 25, 26 и 27 (другие их стороны — на GND), а светодиод — на GPIO 23 через резистор 220 Ω; название выбранного элемента появляется в мониторе порта на скорости 115200 бод.
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}Логические элементы на Raspberry Pi Pico и MicroPython
В MicroPython логические операторы пишутся английскими словами: and, or, not. Побитовые операторы такие же, как в C++: &, |, ^ и ~. Код ниже читает две кнопки на GP14 и GP15 и показывает результаты AND, OR, NAND, NOR, XOR и XNOR на шести светодиодах на GP16–GP21. Другая сторона каждой кнопки идёт на GND, а каждый светодиод подключается через резистор 220–330 Ω. Если сохранить код в Thonny как main.py, он запускается при каждом включении Pico; если Pico для тебя в новинку, начни со статьи Что такое 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 есть похожая ловушка: ~True даёт -2, потому что bool на самом деле целое число. Чтобы перевернуть бит, используй not x, 1 - x или x ^ 1. Кроме того, операторы and и or в Python не всегда возвращают True или False; они возвращают последнее вычисленное значение, так что 0 or 5 даёт 5. Поэтому в коде используются преобразования int(), чтобы светодиоды получали только 0 или 1.
Идеи проектов с логическими элементами
- Умный ночник (AND): включай свет, когда темно И замечено движение; объедини фоторезистор (LDR) и PIR-датчик в одном условии с &&.
- Свет на лестнице (XOR): управляй одной лампой двумя кнопками внизу и вверху лестницы; вычисляй состояние лампы через XOR и коммутируй сетевую лампу модулем реле.
- Домашняя сигнализация (AND + OR): пока система на охране, включай сирену, если открылась дверь ИЛИ окно. Дверь и окно определяй герконом; подробности в руководстве Сигнализация на Arduino.
- Сейф с двумя ключами (AND): не давай замку открыться, пока два разных человека одновременно не нажмут свои кнопки или пока не подтверждён код на матричной клавиатуре.
- 4-битный калькулятор: складывай два числа, введённые переключателями, по логике полного сумматора и показывай результат на 7-сегментном индикаторе.
- Кнопка для викторины: фиксируй светодиод участника, нажавшего первым, и блокируй остальных; это программная версия защёлки на NAND.
- Проверка чётности: сложи через XOR все биты байта; если результат 1, число единиц нечётное. Бит чётности в последовательной связи вычисляется именно так.
Частые ошибки и как их исправить
| Симптом | Вероятная причина | Решение |
|---|---|---|
| Светодиод мерцает сам и меняется, если поднести руку | Висящий вход, нет стягивающего резистора | Добавь к каждому входу стягивающий или подтягивающий резистор 10 kΩ |
| Микросхема греется | Перепутаны VCC и GND или соединены два выхода | Вывод 14 должен быть VCC, а 7 — GND; никогда не соединяй выходы |
| Ни один элемент не реагирует | Нет питания, или микросхема не стоит поперёк выемки | Измерь мультиметром между выводами 14 и 7, поставь микросхему поперёк выемки |
| Неверные результаты с 74HC02 или CD4011 | Распиновка отличается от 74HC08 | Подключай по таблице выводов из даташита |
| Микросхема потребляет больше тока, чем должна | Неиспользуемые входы оставлены висящими | Соедини все неиспользуемые входы с GND |
| Нестабильные результаты с ESP32 или Pico | Сигнала 3,3 V не хватает для 74HC при 5 V | Питай 74HC от 3,3 V или используй 74HCT |
| if (a & b) неожиданно ложно | & работает побитово; 2 & 1 = 0 | Используй && в условиях |
| if (x & 1 == 0) никогда не выполняется | == вычисляется раньше & | Используй скобки: (x & 1) == 0 |
| Одно нажатие переключает элемент несколько раз | Дребезг контактов | Подожди программно 20–50 мс или используй RC-фильтр + 74HC14 |
Логические элементы — алфавит всего цифрового мира, от зажигания светодиода до процессора, складывающего числа. Когда понятны AND, OR и NOT, читать условие if, правило сигнализации или сдвиговый регистр становится гораздо проще. В приложении BlueGrays есть проекты со светодиодом на кнопке, проекты с кнопками на ESP32 и Raspberry Pi Pico, проект умного освещения лестницы и проект умного освещения с PIR-датчиком и фоторезистором — каждый с пошаговыми схемами и кодом, так что логику элементов из этой статьи можно сразу применить в настоящих проектах.
Частые вопросы
Какие бывают логические элементы и для чего они нужны?
Базовых логических элементов семь: AND, OR, NOT, NAND, NOR, XOR и XNOR. Каждый смотрит на входы со значениями 0 или 1 и по своему правилу выдаёт один выход. Любая цифровая схема, включая процессоры, память, счётчики и калькуляторы, построена из сочетания этих элементов.
Как составить таблицу истинности?
Сначала по числу входов определи число строк: для n входов нужно 2ⁿ строк. Запиши входы в порядке двоичного счёта (00, 01, 10, 11), затем примени к каждой строке правило элемента и заполни столбец выхода. В схемах из нескольких элементов работу облегчает отдельный столбец для каждого промежуточного выхода.
Почему NAND называют универсальным элементом?
Потому что из одних только элементов NAND можно собрать NOT, AND, OR, NOR, XOR и XNOR. Например, соединив два входа NAND вместе, получаешь NOT, два NAND подряд дают AND, а четыре NAND — XOR. Тем же свойством обладает элемент NOR, так что он тоже считается универсальным.
Чем отличаются XOR и XNOR?
XOR выдаёт 1, когда входы различаются, а XNOR — когда входы одинаковы. XNOR — это инверсия XOR, и им проверяют, равны ли два бита. XOR используется в сумматорах, проверках чётности и для переворачивания бита.
Чем отличаются 74HC08 и 74LS08?
Обе содержат четыре двухвходовых элемента AND и имеют одинаковую распиновку. 74HC08 сделана по технологии CMOS, работает от 2–6 V и потребляет очень мало тока; 74LS08 — это TTL, она работает только около 5 V и потребляет больше. Для новых проектов выбирай 74HC, а 74HCT — когда подключаешь сигналы 3,3 V к схеме на 5 V.
Чем отличаются && и & в Arduino?
&& — логический оператор AND; он проверяет, истинны ли оба условия, и возвращает true или false. & — побитовое AND, которое сравнивает каждый бит двух чисел отдельно. Поэтому 2 && 1 — истина, а 2 & 1 — это 0; в условиях if используй &&.
Что собрать после прочтения
Все проекты
Управление светодиодом кнопкой (удержание)
Как дверной звонок: свет горит, пока ты нажимаешь, и гаснет, когда отпускаешь. Arduino всё время слушает кнопку; пока она нажата, светодиод горит, а как только ты убираешь палец, он гаснет. Эта просте

Включение и выключение светодиода кнопкой (вкл/выкл)
Нажми кнопку один раз — свет загорится, нажми ещё раз — погаснет, совсем как выключатель в твоей комнате. Arduino замечает каждое нажатие и переводит светодиод в противоположное состояние, выжидая кор

Управление светодиодом кнопкой на ESP32 (удержание)
Светодиод горит, когда кнопка нажата, и гаснет, когда её отпускают. Показывает, как используются цифровой входной пин ESP32 и встроенный подтягивающий резистор. Режим INPUT_PULLUP избавляет от внешнего резистора.

Управление светодиодом кнопкой на ESP32 (переключение)
При каждом нажатии кнопки состояние светодиода меняется: если горел — гаснет, если не горел — загорается. Классический шаблон переключения. Антидребезг убирает механический шум кнопки, чтобы одно нажатие давало одно переключение.

Светодиод с управлением кнопкой на Pico (удержание)
Первый проект Pico с входом — чтение кнопки! Светодиод горит, пока кнопка нажата, и гаснет после отпускания. Это большой шаг после светодиодных анимаций: сигнал из внешнего мира в Pico. Изучи Pin.IN (режим входа), Pin.PULL_UP (встроенный подтягивающий резистор — стандарт для кнопок) и чтение button.value(). Светодиод на GP14, кнопка на GP2 (встроенный PULL_UP). Нажата = LOW (0), отпущена = HIGH (1) — обратная логика сначала путает, но это промышленный стандарт.

Pico: независимое управление 2 светодиодами с помощью 2 кнопок
2 кнопки, 2 светодиода — полностью независимо друг от друга! Каждая кнопка управляет своим светодиодом: при нажатии BTN1 загорается красный, при нажатии BTN2 — зелёный; нажмёшь обе — горят оба. Изучишь управление несколькими объектами пинов, тернарный оператор (1 if x else 0 — компактный if-else в Python), независимое управление вводом-выводом и карту GPIO.

Умное освещение лестницы и коридора
Ступи на лестницу или в коридор, и свет загорается ступенька за ступенькой в ту сторону, куда ты идёшь. На каждом конце стоит датчик расстояния; мимо какого ни пройдёшь, восемь светодиодов загораются

Умное освещение на ESP32 (PIR + LDR + реле + OLED)
Сделай умное освещение для коридора, ванной или кладовки на ESP32! С PIR-датчиком движения, датчиком освещённости LDR и модулем реле собирается классический сценарий «свет включается при движении в темноте»: если вокруг уже светло, движение свет НЕ включает, и днём энергия экономится. Свет горит 30 секунд; если движение продолжается, таймер сбрасывается, и свет горит дольше. OLED SSD1306 крупно показывает состояние (ON / DAYTIME / WAITING) и обратный отсчёт.
Другие статьи
Приложение BlueGrays
Собери эту схему шаг за шагом в телефоне
Схема подключения, код и список деталей на одном экране. 200+ проектов на Arduino, ESP32 и Pico готовы к сборке.
Наведи камеру телефона
Наведи камеру на код — откроется магазин приложений на телефоне.
или открыть магазин

