Если дисплей или SD-карта на ESP32 молчит при заведомо рабочем скетче, первое, что стоит проверить, — какая шина SPI указана в коде: VSPI или HSPI. У классического ESP32 (модуль ESP32-WROOM-32 и подобные) два пользовательских интерфейса SPI имеют разные выводы по умолчанию, и библиотека, рассчитанная на одну шину, молча «не видит» устройство, подключенное к пинам другой.
Разница между VSPI и HSPI часто вызывает путаницу, потому что по функциональности шины практически идентичны — отличаются прежде всего номера контактов и имена в коде. В этой статье разберем, чем отличаются эти интерфейсы, какие пины они используют, как переключаться между ними в Arduino IDE и каких ошибок стоит избегать.
Что такое SPI на ESP32 и сколько шин доступно
SPI (Serial Peripheral Interface) — синхронный последовательный интерфейс для подключения периферии: дисплеев, SD-карт, датчиков, радиомодулей вроде RFM95 или nRF24L01. Шина использует четыре линии: MOSI, MISO, SCK и линию выбора чипа CS (их может быть несколько — по одной на каждое устройство).
Внутри классического ESP32 аппаратно присутствуют несколько SPI-контроллеров. Два из них зарезервированы под внешнюю flash-память, из которой выполняется прошивка, и трогать их нельзя. Разработчику доступны два оставшихся, известные как HSPI и VSPI. В документации Espressif они фигурируют также как SPI2 и SPI3 соответственно.
В чем отличие VSPI от HSPI
Короткий ответ: функциональной разницы нет. Оба контроллера поддерживают режимы ведущего устройства (master), работу с DMA, настройку частоты и режимов SPI (Mode 0–3). Исторически буквы в названиях расшифровываются как «V» — от слова, связанного с внутренней нумерацией периферии чипа, и «H» — аналогично; для пользователя это просто имена двух равнозначных портов.
Практическое отличие заключается в трех моментах:
- 📌 Распиновка по умолчанию. VSPI и HSPI выведены на разные GPIO, и библиотеки используют именно эти наборы, если пины не переопределены явно.
- 📌 Имена объектов в коде. В Arduino-ядре ESP32 шина по умолчанию (
SPI) обычно привязана к VSPI, а для HSPI создается отдельный экземпляр классаSPIClass. - 📌 Конфликты с другой периферией. Пины HSPI частично пересекаются с контактами, задействованными при работе некоторых режимов, поэтому при нехватке выводов выбор шины имеет значение.
⚠️ Внимание: контроллеры SPI0/SPI1 обслуживают внешнюю flash-память с прошивкой. Попытка использовать их пины для своей периферии приведет к сбоям загрузки и работы ESP32. Для своих устройств применяйте только HSPI и VSPI.
Распиновка VSPI и HSPI по умолчанию
Для классического ESP32 принята следующая стандартная распиновка. Именно эти номера используются, когда вы вызываете SPI.begin() без аргументов или берете готовый пример из библиотеки.
| Сигнал | VSPI (SPI3) | HSPI (SPI2) |
|---|---|---|
| SCK (тактирование) | GPIO 18 | GPIO 14 |
| MISO | GPIO 19 | GPIO 12 |
| MOSI | GPIO 23 | GPIO 13 |
| CS (по умолчанию) | GPIO 5 | GPIO 15 |
Обратите внимание: пины можно переназначить — у ESP32 есть матрица GPIO, позволяющая вывести сигналы SPI почти на любые свободные выводы. Поэтому «стандартная» распиновка — это лишь значение по умолчанию, а не жесткое ограничение. Однако GPIO 12 — страппинг-пин: высокий уровень на нем во время загрузки может помешать старту ESP32, поэтому при использовании HSPI следите, чтобы подключенное устройство не подтягивало MISO к питанию в момент включения.
Как выбрать и настроить шину в Arduino IDE
Если устройство одно, проще всего ничего не менять: объект SPI уже привязан к VSPI, и большинство библиотек (например, для дисплеев TFT или SD-карт) работают с ним из коробки. Нужно лишь подключить периферию к пинам 18, 19, 23 и выбранному CS.
Для HSPI создается отдельный экземпляр класса. Типовой фрагмент выглядит так:
#include <SPI.h>
SPIClass hspi(HSPI);
void setup() {
hspi.begin(14, 12, 13, 15); // SCK, MISO, MOSI, CS
}
Многие библиотеки принимают ссылку на объект шины — например, SD.begin(csPin, hspi) для SD-карты. Перед подключением проверьте в документации конкретной библиотеки, поддерживает ли она передачу пользовательского объекта SPIClass: если нет, придется либо использовать VSPI, либо править код библиотеки.
☑️ Проверка перед запуском SPI-устройства на ESP32
Использование двух шин одновременно
Главный сценарий, где различие VSPI и HSPI становится практически важным, — это два независимых SPI-устройства с несовместимыми настройками. Например, быстрый дисплей и медленный датчик с разными режимами SPI. Разведя их по разным шинам, вы избавляетесь от необходимости постоянно перенастраивать частоту и режим при обращении к каждому устройству.
Альтернатива — повесить оба устройства на одну шину с разными CS. Это работает, если устройства совместимы по режиму SPI и умеют корректно освобождать линию MISO. На практике некоторые модули (особенно дешевые платы с SD-картами) не отпускают MISO, что ломает обмен с соседним устройством на той же шине. В таком случае вынос проблемного модуля на вторую шину — простое и надежное решение.
Типичные ошибки при работе с VSPI и HSPI
Большинство проблем связано не с самими шинами, а с несоответствием кода и разводки. Вот что проверять в первую очередь:
- 🔧 Неверные пины. Код рассчитан на VSPI, а устройство подключено к пинам HSPI (или наоборот). Сверьте схему с вызовом
begin(). - 🔧 Перепутанные MISO и MOSI. Линии соединяются «напрямую»: MOSI контроллера — к входу устройства, MISO — к выходу. Перекрестное подключение — частая причина «тишины» на шине.
- 🔧 Проблема GPIO 12. На HSPI линия MISO — это страппинг-пин. Если модуль подтягивает его вверх, ESP32 может не стартовать после сброса.
- 🔧 Логические уровни. ESP32 — устройство 3.3 В. Пятивольтовые сигналы на входах могут со временем повредить пины; используйте согласование уровней, если модуль питается от 5 В.
⚠️ Внимание: распиновка и количество SPI-шин отличаются у других чипов семейства — ESP32-S2, ESP32-S3, ESP32-C3. Код, написанный для классического ESP32 с HSPI/VSPI, может потребовать адаптации. Всегда сверяйтесь с даташитом именно вашего чипа, а не с гайдом «по ESP32 вообще».
Почему шины называются именно HSPI и VSPI
Названия уходят корнями во внутреннюю периферию чипов Espressif: в ранних SoC семейства контроллеры нумеровались, и для пользовательских портов закрепились обозначения HSPI (SPI2) и VSPI (SPI3). Практического смысла в буквах для разработчика нет — это просто устоявшиеся имена двух равнозначных аппаратных интерфейсов, которые используются в Arduino-ядре и ESP-IDF.
Какую шину выбрать для проекта
Если проект простой и устройство одно — берите VSPI: это шина по умолчанию, с ней работает максимум готовых примеров и библиотек. Меньше кода, меньше поводов для ошибок.
HSPI логично задействовать, когда пины VSPI уже заняты, когда нужно изолировать капризное устройство на отдельной шине или когда схема платы удобнее разводится через GPIO 12–15. При этом помните про особенность GPIO 12 при загрузке. Если же свободных пинов критически не хватает, рассмотрите вариант одной шины с несколькими CS — при условии, что устройства совместимы по режимам и корректно освобождают MISO.
FAQ: частые вопросы про VSPI и HSPI
Чем VSPI отличается от HSPI по скорости?
Ничем. Оба контроллера аппаратно эквивалентны и поддерживают одинаковые частоты и режимы. Реальная скорость обмена зависит от настроек в коде, длины проводов и возможностей подключенного устройства, а не от выбора шины.
Можно ли использовать VSPI и HSPI одновременно?
Да. Это независимые аппаратные контроллеры, и они могут работать параллельно, каждый со своей периферией. Для этого создаются два объекта: стандартный SPI (VSPI) и отдельный SPIClass hspi(HSPI).
Почему ESP32 не стартует после подключения устройства к HSPI?
Возможная причина — линия MISO на GPIO 12. Это страппинг-пин, и высокий уровень на нем в момент загрузки меняет параметры старта чипа. Проверьте, не подтягивает ли подключенный модуль эту линию к питанию; при необходимости перенесите MISO на другой пин через матрицу GPIO.
Можно ли назначить VSPI на другие пины?
Да, у ESP32 есть матрица переназначения сигналов. Пины задаются при вызове SPI.begin(sck, miso, mosi, cs). Учтите, что часть GPIO имеет ограничения (только вход, страппинг-пины), поэтому выбор стоит сверять с распиновкой вашей платы.
Работают ли VSPI и HSPI на ESP32-S3 или ESP32-C3?
Архитектура SPI у этих чипов отличается от классического ESP32: количество пользовательских шин и их имена могут быть другими. Код с явным использованием HSPI/VSPI следует проверять и при необходимости адаптировать под документацию конкретного чипа.