Embedded HandbookПриложения
Все разделы › XVIII. ESP32: второй микроконтроллер
ESP32 · уровень средний · 13 мин чтения
Открыть в интерактивном справочнике

153. GPIO и ШИМ на ESP32: выводы, электрика, strapping, матрица сигналов, LEDC, MCPWM

Вывод STM32 из раздела 8 — это регистры порта, альтернативная функция из таблицы и ток до 20 мА. У ESP32 всё то же по смыслу и другое по устройству: номера выводов с дырками, шесть из них заняты флеш-памятью, шесть умеют только слушать, пять при сбросе решают судьбу чипа, а любой сигнал периферии можно вывести почти на любой вывод через матрицу. ШИМ здесь два разных блока: LEDC для светодиодов и регуляторов, MCPWM для двигателей. Раздел опирается на три источника: программу в QEMU (_verify/esp153/), заголовки ESP-IDF и таблицы даташита ESP32 версии 5.3 (выписка datasheet_dc.txt); аналоговую часть — ШИМ через RC — считает ngspice.

Как это называется в документации

Оригинал Перевод
GPIO pad контактная площадка вывода со своим буфером
IO_MUX мультиплексор вывода: прямой путь к «родной» функции
GPIO matrix матрица: любой сигнал периферии на любой вывод
input-only pins выводы только на вход (34–39), без подтяжек
strapping pins выводы, защёлкиваемые при сбросе (0, 2, 5, 12, 15)
drive strength (drive capability) сила выхода: четыре ступени тока
VIH / VIL, VOH / VOL пороги входа, уровни выхода
IOH / IOL ток выхода в единице и в нуле
LEDC (LED PWM controller) ШИМ-контроллер общего назначения
duty resolution, hpoint разрядность скважности, точка включения в периоде
high-speed / low-speed mode два блока LEDC: с аппаратным и программным обновлением
MCPWM (motor control PWM) ШИМ для двигателей: пары выходов, мёртвое время, защита
operator, generator, comparator оператор, генератор, компаратор MCPWM

153.1 Номера выводов: где дырки

Программа перебирает номера через макросы драйвера:

    for (int i = 0; i < SOC_GPIO_PIN_COUNT; i++) {
        valid += GPIO_IS_VALID_GPIO(i);
        outputs += GPIO_IS_VALID_OUTPUT_GPIO(i);
    }
номеров GPIO 40, из них существуют 35, с выходом 29
нет на кристалле: 24 28 29 30 31
только вход: 34 35 36 37 38 39

Номеров 40, существуют 35: 24 и 28–31 на кристалле нет. GPIO20 по заголовку существует, но выведен только у части корпусов, например ESP32-PICO-V3; у обычного чипа и модуля WROOM-32 его нет — там выводов 34, из них 28 с выходом. Шесть последних — только вход, и подтяжек у них нет: под кнопку на GPIO34 нужен внешний резистор. Ещё шесть, 6–11, существуют и умеют быть выходом, но на модуле к ним припаяна флеш-память (раздел 150) — драйвер их не запрещает, а программа, тронув их, перестаёт читать собственный код. Драйвер проверяет только то, что знает:

GPIO2  как выход: ESP_OK
GPIO34 как выход: ESP_ERR_INVALID_ARG
GPIO24 как выход: ESP_ERR_INVALID_ARG

Так что для изделия на WROOM-32 остаются 28 выходов минус 6 флеш-памяти минус strapping-выводы, которым при сбросе нельзя мешать, — около двух десятков свободных.

Вывод ESP32: сигнал периферии идёт либо напрямую через IO_MUX, либо через матрицу на любой вывод; у площадки — подтяжки 45 кОм, четыре ступени силы выхода, а пять выводов защёлкиваются при сбросе


153.2 Электрика вывода: числа даташита

Таблица 5-3 даташита (3,3 В, 25 °C):

Параметр Значение Что это значит
VIH ≥ 0,75 × VDD = 2,475 В порог единицы на входе
VIL ≤ 0,25 × VDD = 0,825 В порог нуля
вход, максимум VDD + 0,3 = 3,6 В 5 В на вход нельзя
VOH / VOL ≥ 0,8 × VDD / ≤ 0,1 × VDD уровни выхода
IOH 40 мА при VOH ≥ 2,64 В, сила выхода на максимуме ток «в единице» с одного вывода
IOL 28 мА при VOL = 0,495 В ток «в нуле»
RPU / RPD 45 кОм внутренние подтяжки
CIN 2 пФ ёмкость вывода
IIH / IIL 50 нА ток утечки входа

Две оговорки из той же таблицы. Во-первых, 40 мА — на максимальной силе выхода, а по умолчанию она средняя: ступеней четыре, от 0 (слабая) до 3, по умолчанию 2 (GPIO_DRIVE_CAP_DEFAULT в заголовке). Программа ставит ступень 3 и читает её обратно — в эмуляторе получается 0, потому что регистров выводов в нём нет (153.8), а на плате прочтётся 3:

сила выхода GPIO2: 0 (ступени 0..3, по умолчанию 2)

Во-вторых, 40 мА — с одного вывода; чем больше выводов в одном домене питания отдают ток одновременно, тем меньше на каждый: даташит называет снижение примерно до 29 мА. Для выходов домена VDD_SDIO (выводы флеш-памяти) предел 20 мА. Правило то же, что в разделе 62: не вешать на выводы то, что можно повесить на транзистор.

Подтяжки 45 кОм — слабые: для I²C они не годятся (раздел 95 просит 1,5–4,7 кОм), для кнопки в шумном месте тоже лучше внешние 10 кОм.


153.3 Strapping: пять выводов при сбросе

При сбросе чип защёлкивает уровни пяти выводов и по ним решает, как загружаться (таблица 3-1 даташита):

Вывод Подтяжка внутри Бит по умолчанию За что отвечает
GPIO0 вверх 1 1 — загрузка из флеш-памяти, 0 — режим прошивки
GPIO2 вниз 0 вместе с GPIO0 = 0 выбирает прошивку по UART
MTDI (GPIO12) вниз 0 напряжение питания флеш-памяти: 0 — 3,3 В, 1 — 1,8 В
MTDO (GPIO15) вверх 1 печать журнала ПЗУ в UART0 при старте
GPIO5 вверх 1 тактирование SDIO-ведомого

Загрузка из флеш-памяти — при GPIO0 = 1 независимо от GPIO2; режим прошивки — GPIO0 = 0 и GPIO2 = 0 (таблица 3-3). Отсюда две кнопки DevKit: EN дёргает сброс, BOOT притягивает GPIO0 к земле. Защёлки держат значения до выключения питания, и после сброса выводы свободны — но что бы ни висело на них снаружи, оно не должно тянуть уровень в момент сброса. Самый коварный — GPIO12: подтянутый вверх датчиком, он переведёт питание флеш-памяти на 1,8 В, и модуль с 3,3-вольтовой микросхемой не загрузится вовсе. Если GPIO12 всё же нужен с подтяжкой вверх, напряжение флеш-памяти закрепляют в eFuse: espefuse.py set_flash_voltage 3.3V. Это необратимо, и после этого уровень GPIO12 при сбросе не читается.


153.4 IO_MUX и матрица

У каждого вывода есть несколько «родных» функций через IO_MUX — так подключены флеш-память и SPI на своих выводах, это самый быстрый путь. Всё остальное идёт через матрицу GPIO: у периферии пронумерованные сигналы — в заголовке gpio_sig_map.h 384 имени с номерами до 255, а 256 означает «обычный GPIO», — и любой из них можно назначить почти на любой вывод:

имён сигналов в gpio_sig_map.h: 384, наибольший номер: 256, SIG_GPIO_OUT_IDX 256
U0RXD_IN_IDX 14
U0TXD_OUT_IDX 14
SPICLK_OUT_IDX 0
I2CEXT0_SCL_IN_IDX 29
LEDC_HS_SIG_OUT0_IDX 71
PWM0_OUT0A_IDX 32

Драйверы делают это сами: ledc_channel_config с gpio_num = 2 соединяет сигнал LEDC_HS_SIG_OUT0 с выводом 2 через матрицу, и переназначить UART, I²C или ШИМ на другие выводы — вопрос одного числа в структуре, а не таблицы альтернативных функций. Цена матрицы — лишняя задержка и предел частоты: SPI через матрицу медленнее, чем через IO_MUX, и для 40–80 МГц выбирают родные выводы.


153.5 LEDC: частота против разрядности

LEDC — 16 каналов: два режима по 8 каналов и по 4 таймера, таймер до 20 бит, тактирование 80 МГц. Скважность задаётся в тиках таймера, и чем выше частота ШИМ, тем меньше тиков в периоде — разрядность и частота торгуются друг за друга по формуле f_max = 80 МГц / 2^бит. Драйвер считает это сам:

    for (size_t i = 0; i < sizeof freqs / sizeof freqs[0]; i++) {
        uint32_t bits = ledc_find_suitable_duty_resolution(80000000, freqs[i]);
       50 Гц: до 20 бит (шаг 0.0001 %)
     1000 Гц: до 16 бит (шаг 0.0015 %)
     5000 Гц: до 13 бит (шаг 0.0122 %)
    25000 Гц: до 11 бит (шаг 0.0488 %)
   100000 Гц: до  9 бит (шаг 0.1953 %)
   312500 Гц: до  8 бит (шаг 0.3906 %)
  1000000 Гц: до  6 бит (шаг 1.5625 %)

Сервопривод на 50 Гц получает все 20 бит, светодиод на 5 кГц — 13, а ШИМ на 312,5 кГц, которым питают преобразователь, — только 8, то есть шаг 0,4 %. Попросить лишнего нельзя:

ledc_timer_config 5 кГц / 13 бит: ESP_OK
ledc_timer_config 100 кГц / 13 бит: ESP_FAIL

Настройка — два вызова, таймер и канал:

    ledc_timer_config_t tc = { .speed_mode = LEDC_HIGH_SPEED_MODE, .timer_num = LEDC_TIMER_0, .duty_resolution = LEDC_TIMER_13_BIT,
                               .freq_hz = 5000, .clk_cfg = LEDC_AUTO_CLK };
    ledc_channel_config_t cc = { .gpio_num = 2, .speed_mode = LEDC_HIGH_SPEED_MODE, .channel = LEDC_CHANNEL_0, .timer_sel = LEDC_TIMER_0,
                                 .duty = 4096, .hpoint = 0 };

Скважность 4096 из 8192 — 50 %. Дальше ledc_set_duty и ledc_update_duty: первый готовит значение, второй применяет — поэтому забытый update и есть самая частая ошибка с LEDC. Режим high-speed обновляет скважность аппаратно на границе периода, low-speed — программно; у второго есть свой тактовый генератор, работающий в лёгком сне. Аппаратное плавное изменение ledc_fade доводит скважность до цели за заданное время без участия процессора.

Разрядность LEDC по частоте ШИМ: от 20 бит на 50 Гц до 6 бит на 1 МГц


153.6 ШИМ как ЦАП: цена частоты

Тот же таймер даёт либо точность, либо частоту, и на RC-фильтре это видно. ngspice: 3,3 В, скважность 50 %, фильтр 10 кОм / 100 нФ (постоянная времени 1 мс), три пары с одного таймера:

f=1k ripple_V=0.808228
f=5k ripple_V=0.164858
f=312.5k ripple_V=0.002636

Размах пульсаций при 50 % — U · th(1/(4·f·RC)), это и считает ngspice. 16 бит на 1 кГц дают пульсации 0,81 В — половину шкалы, никакой точности; 13 бит на 5 кГц — 0,16 В; 8 бит на 312,5 кГц — 2,6 мВ, но шаг скважности 0,4 % — те же 13 мВ. Компромисс для ШИМ-ЦАП из раздела 50 на ESP32 выглядит так: 10–12 бит на 20–80 кГц и фильтр второго порядка.


153.7 MCPWM: ШИМ для двигателей

Второй блок — MCPWM, два одинаковых модуля:

SOC_MCPWM_GROUPS (2) 
SOC_MCPWM_TIMERS_PER_GROUP (3) 
SOC_MCPWM_OPERATORS_PER_GROUP (3) 
SOC_MCPWM_COMPARATORS_PER_OPERATOR (2) 
SOC_MCPWM_GENERATORS_PER_OPERATOR (2) 
SOC_MCPWM_GPIO_FAULTS_PER_GROUP (3) 
SOC_MCPWM_CAPTURE_TIMERS_PER_GROUP (1) 

В каждом модуле три таймера, три оператора по два генератора — 12 выходов на чип, парами A/B под верхний и нижний ключ полумоста с мёртвым временем, три входа аварии, которые аппаратно гасят выходы, и таймер захвата для датчиков Холла и энкодера. Это то, что в STM32 делает таймер TIM1 с комплементарными выходами (раздел 13): мост, трёхфазный двигатель, синхронный выпрямитель. Для светодиода и сервопривода MCPWM избыточен — там LEDC.


153.8 Что не умеет эмулятор

GPIO2: записали 1 — читаем 0, записали 0 — читаем 0
ledc_get_freq: 5000 Гц, ledc_get_duty: 0

Вывод в режиме INPUT_OUTPUT на кристалле читает собственный уровень — здесь читает ноль; скважность, только что записанная в канал, читается нулём. У QEMU для ESP32 нет модели выводов и LEDC: регистры пишутся в пустоту. Всё, что выше, — проверка логики драйвера и арифметики; уровни и осциллограммы проверяют на плате. Это граница эмулятора, и полезно знать её заранее, чтобы не искать в своём коде ошибку, которой нет.


153.9 Грабли

Симптом Причина
gpio_set_direction вернул ESP_ERR_INVALID_ARG вывод 34–39 только вход или номера нет на кристалле
кнопка на GPIO34 «плавает» у 34–39 нет внутренних подтяжек
после gpio_config на GPIO6–11 плата перезагружается это выводы флеш-памяти
плата не стартует с подключённой периферией что-то тянет strapping-вывод при сбросе; GPIO12 вверх = 1,8 В на флеш
выход «не тянет» светодиод с резистором 30 Ом сила выхода 2 из 3 и 40 мА только при VOH ≥ 2,64 В
датчик на 5 В сжёг вход вход до VDD + 0,3 = 3,6 В
ledc_timer_config → ESP_FAIL частота × 2^бит больше 80 МГц
ledc_set_duty ничего не меняет забыт ledc_update_duty
ШИМ-ЦАП шумит низкая частота ради разрядности; поднять частоту, фильтр 2-го порядка
SPI через матрицу не даёт 80 МГц родные выводы IO_MUX
в эмуляторе GPIO читается нулём QEMU не моделирует выводы

153.10 Итоги

Полные исходники

main.c — GPIO и ШИМ LEDC на ESP32: что разрешает драйвер.

/* Раздел 153: GPIO и ШИМ LEDC на ESP32 — что разрешает драйвер, что считает сам. */
#include <stdio.h>
#include "driver/gpio.h"
#include "driver/ledc.h"
#include "esp_err.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "soc/gpio_num.h"
#include "soc/soc_caps.h"

static const char *TAG = "gpio153";

static void try_output(int pin)
{
    esp_err_t e = gpio_set_direction(pin, GPIO_MODE_OUTPUT);
    printf("GPIO%-2d как выход: %s\n", pin, esp_err_to_name(e));
}

void app_main(void)
{
    /* какие номера вообще существуют и какие умеют быть выходом — по маскам soc_caps */
    int valid = 0, outputs = 0;
    for (int i = 0; i < SOC_GPIO_PIN_COUNT; i++) {
        valid += GPIO_IS_VALID_GPIO(i);
        outputs += GPIO_IS_VALID_OUTPUT_GPIO(i);
    }
    printf("номеров GPIO %d, из них существуют %d, с выходом %d\n", SOC_GPIO_PIN_COUNT, valid, outputs);
    printf("нет на кристалле:");
    for (int i = 0; i < SOC_GPIO_PIN_COUNT; i++)
        if (!GPIO_IS_VALID_GPIO(i)) printf(" %d", i);
    printf("\nтолько вход:");
    for (int i = 0; i < SOC_GPIO_PIN_COUNT; i++)
        if (GPIO_IS_VALID_GPIO(i) && !GPIO_IS_VALID_OUTPUT_GPIO(i)) printf(" %d", i);
    printf("\n");

    esp_log_level_set("gpio", ESP_LOG_NONE);        /* драйвер и так вернёт код ошибки */
    try_output(2);
    try_output(34);
    try_output(24);

    /* выход с обратным чтением: режим INPUT_OUTPUT читает свой же уровень */
    gpio_config_t io = { .pin_bit_mask = 1ULL << 2, .mode = GPIO_MODE_INPUT_OUTPUT, .pull_up_en = 0, .pull_down_en = 0, .intr_type = GPIO_INTR_DISABLE };
    ESP_ERROR_CHECK(gpio_config(&io));
    gpio_set_level(2, 1);
    int a = gpio_get_level(2);
    gpio_set_level(2, 0);
    int b = gpio_get_level(2);
    printf("GPIO2: записали 1 — читаем %d, записали 0 — читаем %d\n", a, b);

    /* сила выхода: четыре ступени */
    gpio_drive_cap_t cap;
    gpio_set_drive_capability(2, GPIO_DRIVE_CAP_3);
    gpio_get_drive_capability(2, &cap);
    printf("сила выхода GPIO2: %d (ступени 0..%d, по умолчанию %d)\n", (int)cap, (int)GPIO_DRIVE_CAP_MAX - 1, (int)GPIO_DRIVE_CAP_DEFAULT);

    /* LEDC: сколько бит разрешения вмещает частота при тактировании 80 МГц */
    printf("LEDC: каналов %d × 2 режима, таймер до %d бит\n", SOC_LEDC_CHANNEL_NUM, SOC_LEDC_TIMER_BIT_WIDTH);
    const uint32_t freqs[] = { 50, 1000, 5000, 25000, 100000, 312500, 1000000 };
    for (size_t i = 0; i < sizeof freqs / sizeof freqs[0]; i++) {
        uint32_t bits = ledc_find_suitable_duty_resolution(80000000, freqs[i]);
        printf("  %7lu Гц: до %2lu бит (шаг %.4f %%)\n", (unsigned long)freqs[i], (unsigned long)bits, bits ? 100.0 / (1u << bits) : 0.0);
    }
    ledc_timer_config_t tc = { .speed_mode = LEDC_HIGH_SPEED_MODE, .timer_num = LEDC_TIMER_0, .duty_resolution = LEDC_TIMER_13_BIT,
                               .freq_hz = 5000, .clk_cfg = LEDC_AUTO_CLK };
    printf("ledc_timer_config 5 кГц / 13 бит: %s\n", esp_err_to_name(ledc_timer_config(&tc)));
    tc.freq_hz = 100000;
    printf("ledc_timer_config 100 кГц / 13 бит: %s\n", esp_err_to_name(ledc_timer_config(&tc)));
    tc.freq_hz = 5000;
    ledc_timer_config(&tc);
    ledc_channel_config_t cc = { .gpio_num = 2, .speed_mode = LEDC_HIGH_SPEED_MODE, .channel = LEDC_CHANNEL_0, .timer_sel = LEDC_TIMER_0,
                                 .duty = 4096, .hpoint = 0 };
    printf("ledc_channel_config GPIO2, скважность 4096/8192: %s\n", esp_err_to_name(ledc_channel_config(&cc)));
    printf("ledc_get_freq: %lu Гц, ledc_get_duty: %lu\n", (unsigned long)ledc_get_freq(LEDC_HIGH_SPEED_MODE, LEDC_TIMER_0),
           (unsigned long)ledc_get_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0));
    ESP_LOGI(TAG, "done");
}

Дальше: раздел 154 — АЦП и ЦАП ESP32.

Открыть в интерактивном справочнике