1. Введение: что такое GPIO и зачем он нужен
GPIO (General‑Purpose Input/Output) — универсальные цифровые выводы микроконтроллера, способные конфигурироваться как вход или выход. Это базовый интерфейс для взаимодействия МК с внешним миром:
- управление светодиодами, реле, двигателями;
- считывание состояния кнопок, датчиков, переключателей;
- реализация простых протоколов (bit‑banging: I²C, UART, SPI).
Ключевые свойства GPIO:
- уровень напряжения: обычно 3,3 В или 5 В;
- ток нагрузки: 2–20 мА на вывод (зависит от МК);
- программируемая подтяжка (pull‑up/pull‑down);
- возможность прерываний по изменению состояния.
2. Архитектурные особенности GPIO
2.1. Регистровая модель
Каждый порт GPIO управляется набором регистров (адреса зависят от МК):
- DDRx (Data Direction Register) — настройка направления (0 = вход, 1 = выход);
- PORTx — запись данных на выход или управление подтяжкой;
- PINx — чтение текущего состояния выводов.
Пример для AVR (ATmega328P):
DDRB = 0b00000011; // PB0 и PB1 — выходы
PORTB = 0b00000010; // Установить PB1 = 1
uint8_t state = PINB; // Считать состояние порта B
2.2. Мультиплексирование функций
Выводы GPIO часто совмещены с периферией (UART, SPI, ADC). Приоритет определяет:
- конфигурация регистров периферии;
- порядок инициализации (сначала периферия, потом GPIO).
2.3. Электрические характеристики
- Вход:
- порог срабатывания: ~0,3 VCC (низкий), ~0,7 VCC (высокий);
- входной ток утечки: микроамперы.
- Выход:
- логический «0»: 0–0,4 В;
- логическая «1»: VCC–0,4 В;
- максимальный ток: указан в datasheet (например, 20 мА для STM32F1).
Важно! Превышение тока ведёт к повреждению вывода. Используйте токоограничивающие резисторы.
3. Режимы работы GPIO
3.1. Вход (Input)
- Floating (без подтяжки) — потенциал плавает; требует внешнего резистора.
- Pull‑up — внутренний резистор подтянут к VCC (обычно 20–50 кОм).
- Pull‑down — внутренний резистор подтянут к GND.
Применение:
- кнопки без внешних резисторов (pull‑up);
- датчики с открытым коллектором (pull‑down).
3.2. Выход (Output)
- Push‑Pull — активный драйвер: выдаёт «0» (GND) или «1» (VCC).
- Open‑Drain — только «0» или высокоимпедансное состояние (требуется внешний pull‑up).
Сравнение:
- Push‑Pull: быстрее, подходит для управления нагрузками.
- Open‑Drain: позволяет соединять несколько выходов (wire‑OR), совместим с I²C.
3.3. Альтернативные функции (Alternate Function)
Вывод подключается к модулю периферии:
- USART_TX, SPI_MOSI, I²C_SCL и т. д.
- требует настройки регистров периферии и мультиплексора.
4. Программирование GPIO: примеры для разных платформ
4.1. AVR (ATmega328P)
// Инициализация
DDRD |= (1 << PD2); // PD2 — выход
DDRB &= ~(1 << PB0); // PB0 — вход
PORTB |= (1 << PB0); // Pull‑up на PB0
// Запись
PORTD |= (1 << PD2); // Установить PD2 = 1
PORTD &= ~(1 << PD2); // Установить PD2 = 0
// Чтение
if (PINB & (1 << PB0)) {
// Кнопка на PB0 нажата
}
4.2. STM32 (Cortex‑M, HAL)
__HAL_RCC_GPIOA_CLK_ENABLE(); // Включить тактирование GPIOA
GPIO_InitTypeDef GPIO_InitStruct = {0};
// Настройка выхода
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Запись
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
// Настройка входа
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Чтение
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) {
// Сигнал на входе
}
4.3. ESP32
#include "driver/gpio.h"
// Инициализация
gpio_pad_select_gpio(GPIO_NUM_2);
gpio_set_direction(GPIO_NUM_2, GPIO_MODE_OUTPUT);
gpio_set_pull_mode(GPIO_NUM_2, GPIO_PULLUP_ONLY);
// Запись
gpio_set_level(GPIO_NUM_2, 1);
// Чтение
uint32_t level = gpio_get_level(GPIO_NUM_4);
5. Практические схемы подключения
5.1. Управление светодиодом
- Схема: анод светодиода → резистор (220–470 Ом) → выход МК; катод → GND.
- Расчёт резистора:R=IFVCC−VF где VF — прямое напряжение светодиода (2 В), IF — ток (5 мА).
Для VCC=3,3 В:R=0,0053,3−2=260 Ом(берём 270 Ом).
5.2. Подключение кнопки
- С pull‑up: кнопка между выводом МК и GND; в ПО — проверка на «0» при нажатии.
- С pull‑down: кнопка между выводом МК и VCC; проверка на «1».
- Дебаунсинг: программная фильтрация дребезга:
static uint32_t last_press = 0; if (HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN) == GPIO_PIN_RESET) { if (HAL_GetTick() - last_press > 50) { // Задержка 50 мс last_press = HAL_GetTick(); // Обработка нажатия } }
5.3. Управление реле/транзистором
- Схема: выход МК → токоограничивающий резистор → база NPN‑транзистора; коллектор → обмотка реле; эмиттер → GND.
- Защита: диод параллельно обмотке реле (для подавления ЭДС самоиндукции).
6. Оптимизация работы с GPIO
6.1. Быстрое переключение (bit‑banging)
Для протоколов без аппаратной поддержки:
- использование регистров
BSRR(STM32) для атомарной установки/сброса битов; - минимизация задержек между операциями.
Пример для STM32:
GPIOA->BSRR = GPIO_PIN_5; // Установить PA5 = 1 (без чтения регистра)
GPIOA->BRR = GPIO_PIN_5; // Сбросить PA5 = 0
6.2. Групповые операции
- Запись нескольких битов за одну операцию:
PORTB = (PORTB & 0xF0) | 0x05; // Установить биты 0 и 2 - Использование би



