Перейти к основному содержимому
  1. Rust/

ESP32 + Rust: Быстрый старт с нуля (помигаем светодиодом)

818 слов·4 минуты· loading · loading · ·
Rust - Эта статья часть цикла.
Статей прочитано 0/1
0%
📚 Введение и дополнительные материалы
58 ESP32 + Rust: Быстрый старт с нуля (помигаем светодиодом) (текущая)
Не прочитана

Программирование микроконтроллеров на Rust становится простым, как только вы один раз настроите окружение. В этом гиде мы с нуля подготовим инструменты, разберем код прошивки и заставим светиться встроенный светодиод на плашке ESP32.


1. Проверяем подключение платы
#

Вставьте USB-кабель в плату ESP32 и убедитесь, что компьютер увидел серийный порт:

# На macOS:
ls /dev/cu.usbserial*

# На Linux:
ls /dev/ttyUSB*

Макроснимок платы ESP32-WROOM-32 DevKit v1


2. Настраиваем окружение (2 способа)
#

Выберите один из двух удобных способов сборки проекта:

Вариант А: Нативная установка через espup (Рекомендуется)
#

Самый быстрый способ для Mac, Linux и Windows. Устанавливаем официальный тулчейн espup и прошивальщик espflash:

cargo install espup
cargo install espflash
espup install

Вариант Б: Изолированная сборка в Docker
#

Если у вас установлен Docker и вы не хотите устанавливать тулчейны в систему, используйте официальный легкий образ Espressif под ESP32:

# Скачиваем образ с преднастроенным тулчейном Rust для ESP32
docker pull espressif/idf-rust:esp32_1.93.0.0

# Компилируем проект внутри Docker-контейнера
docker run --rm -v $PWD:/project -w /project espressif/idf-rust:esp32_1.93.0.0 cargo build

3. Генерируем проект шаблона
#

Для генерации готовой структуры проекта используем cargo-generate и официальный шаблон esp-rs:

cargo install cargo-generate
cargo generate esp-rs/esp-idf-template cargo

В появившемся интерактивном меню задаем параметры:

  • Project Name: esp32-blink
  • MCU: esp32
  • Advanced Options: false

Утилита автоматически создаст структуру проекта с файлом конфигурации .cargo/config.toml:

[build]
target = "xtensa-esp32-none-elf"

[target.xtensa-esp32-none-elf]
runner = "espflash flash --monitor --chip esp32"

4. Разбор кода (src/main.rs)
#

Откройте сгенерированный файл src/main.rs. Программа на микроконтроллере отличается от обычной программы на ПК: здесь отключена библиотека std (#![no_std]) и стандартная точка входа C-runtime (#![no_main]).

Интерактивные слайды кода:
#

Слайд 1. Каркас no_std и Паника
 1// ?ignore
 2// ?hidden:start
 3#![no_std]
 4#![no_main]
 5
 6use core::panic::PanicInfo;
 7// ?hidden:end
 8
 9#[panic_handler]
10fn panic(_info: &PanicInfo) -> ! {
11    // В реальной прошивке здесь логгируют ошибку в UART
12    loop {}
13}
14
15fn main() {
16    // Точка входа прошивки без стандартной библиотеки std
17}
18

Разбор каркаса #![no_std]

  • #![no_std]: Отключает тяжелый C-runtime и стандартную библиотеку OS.
  • #![no_main]: Отменяет поиск стандартной точки входа main.
  • #[panic_handler]: Функция, вызываемая компилятором при любой ошибке паники в микроконтроллере.
Слайд 2. Настройка GPIO на выход
 1// ?hidden:start
 2struct GpioPin;
 3struct OutputConfig;
 4struct Output;
 5
 6impl Output {
 7    fn new(_pin: GpioPin, _config: OutputConfig) -> Self {
 8        Output
 9    }
10    fn set_high(&mut self) {}
11    fn set_low(&mut self) {}
12}
13// ?hidden:end
14
15fn configure_gpio() {
16    let pin_gpio2 = GpioPin;
17    let mut led = Output::new(pin_gpio2, OutputConfig);
18
19    // Управляем уровнем напряжения на пине
20    led.set_high(); // 3.3V (Светодиод горит)
21    led.set_low();  // 0.0V (Светодиод гаснет)
22}
23
24fn main() {
25    configure_gpio();
26    println!("GPIO 2 сконфигурирован успешно!");
27}
28

Конфигурирование GPIO в Rust

  • Захват пина: Безопасность типов Rust гарантирует, что пин GPIO2 не может быть одновременно использован в двух разных местах программы.
  • Level::High (3.3V): Подает высокий уровень напряжения на вывод.
  • Level::Low (0.0V): Подает нулевой уровень (заземление).
Слайд 3. Бесконечный цикл мигания
 1// ?hidden:start
 2struct Led {
 3    is_on: bool,
 4}
 5
 6impl Led {
 7    fn toggle(&mut self) {
 8        self.is_on = !self.is_on;
 9    }
10}
11// ?hidden:end
12
13fn blink_simulation() {
14    let mut led = Led { is_on: false };
15
16    for step in 1..=4 {
17        led.toggle();
18        let status = if led.is_on { "ВКЛ (HIGH 💡)" } else { "ВЫКЛ (LOW 🌑)" };
19        println!("[Шаг {}] Состояние светодиода: {}", step, status);
20    }
21}
22
23fn main() {
24    blink_simulation();
25}
26

Бесконечный цикл и переключение состояния

  • led.toggle(): Атомарно меняет состояние выхода с High на Low или наоборот.
  • Delay: Использование аппаратного таймера отсчитывает ровно 1000 мс паузы.
  • loop: Бесконечный цикл гарантирует, что прошивка продолжает работу всё время, пока подается питание.

Итоговый файл src/main.rs:
#

#![no_std]
#![no_main]

use esp_hal::clock::CpuClock;
use esp_hal::delay::Delay;
use esp_hal::gpio::{Level, Output, OutputConfig};
use esp_hal::main;
use esp_println::println;

esp_bootloader_esp_idf::esp_app_desc!();

#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
    println!("PANIC: {:?}", info);
    loop {}
}

#[main]
fn main() -> ! {
    // 1. Получаем контроль над аппаратурой чипа
    let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
    let peripherals = esp_hal::init(config);
    let delay = Delay::new();

    println!("==========================================");
    println!("💡 ESP32 + Rust (Blink LED)");
    println!("==========================================");

    // 2. Настраиваем синий встроенный светодиод (GPIO 2)
    let mut led = Output::new(peripherals.GPIO2, Level::Low, OutputConfig::default());
    let mut count = 0;

    // 3. Бесконечный цикл работы платы
    loop {
        count += 1;
        led.toggle();

        let state = if led.is_set_high() { "ВКЛ (HIGH 💡)" } else { "ВЫКЛ (LOW 🌑)" };
        println!("[#{:03}] Светодиод: {}", count, state);

        delay.delay_millis(1000);
    }
}

5. Прошиваем плату и смотрим результат
#

Запустите сборку и прошивку одной командой:

cargo run --release

Или вызовите espflash напрямую:

espflash flash target/xtensa-esp32-none-elf/release/esp32-blink --monitor

Утилита сама определит подключенный порт (например, /dev/cu.usbserial-0001), скомпилирует проект, загрузит прошивку в флеш-память ESP32 и откроет серийный монитор логов во встроенном терминале VS Code:

Вывод логов утилиты espflash во встроенном терминале VS Code

Анимированная GIF-демонстрация ритмичного мигания встроенного светодиода ESP32

А на самой плате ритмично замигает синий светодиод! 🎉


Проверьте свои знания
#

Пройдите короткий квиз по материалу статьи:


Что дальше?
#

В следующих статьях серии мы продолжим использовать эту настройку для работы с физическими кнопками, прерываниями, датчиками по I2C/SPI и Wi-Fi! 🦀

Статья прочитана
Пожалуйста, оцените насколько статья была вам полезна и понятна
Цикл статей
Rust - Эта статья часть цикла.
Статей прочитано 0/1
0%
📚 Введение и дополнительные материалы
58 ESP32 + Rust: Быстрый старт с нуля (помигаем светодиодом) (текущая)
Не прочитана

Связанные статьи