esp-rs 简介

esp-rs 是一个专注于为 Espressif 系列芯片(如 ESP32、ESP32-S2、ESP32-C3 等)提供 Rust 语言支持的社区和项目。它的目标是为开发者提供一个高效、安全且易于使用的 Rust 开发环境,以便在 Espressif 芯片上进行嵌入式系统开发。

  • 构建工具
存储库描述
esp-rs/rust带有 Xtensa 支持的 Rust 编译器分支
esp-rs/rust-buildRust 编译器 fork 的预构建二进制文件以及安装脚本
  • 硬件抽象层
存储库描述
esp-rs/esp-idf-hal支持 Rust 标准库(std)
esp-rs/esp-hal不支持 Rust 标准库 ( no_std)

Github

Rust 包仓库

Rust 教程

Wokwi 电子模拟器

在这里插入图片描述

开发环境

Rust 环境

# 安装 nightly 版本
rustup install nightly
# 设置默认 Rust 版本
rustup default nightly
# 当前 Rust 版本
rustc --version

esp-rs 环境

  • espup安装

用于安装和维护使用 Rust 为 Espressif SoC 开发应用程序所需的工具链的工具。https://github.com/esp-rs/rust-build

cargo install espup
espup install
. $HOME/export-esp.sh
  • RISC-V 安装

以下指令专门针对基于 RISC-V 架构的 ESP32-C

rustup target add riscv32imc-unknown-none-elf
rustup component add rust-src --toolchain nightly
# 安装 cargo-generate
cargo install cargo-generate
cargo generate -h
# 安装 espflash
cargo install espflash
espflash --help
espflash flash --help

创建 ESP32C3 项目

cargo generate -a esp-rs/esp-template

在这里插入图片描述

项目结构

在这里插入图片描述

  • Cargo.toml
[dependencies]
esp-backtrace = { version = "0.14.0", features = [
    "esp32c3",
    "exception-handler",
    "panic-handler",
    "println",
] }
esp-hal = { version = "0.20.1", features = [ "esp32c3" ] }
esp-println = { version = "0.11.0", features = ["esp32c3", "log"] }
log = { version = "0.4.21" }
  • main.rs
#![no_std]
#![no_main]
#![allow(dead_code)]

use esp_backtrace as _;
use esp_hal::{
    clock::ClockControl, 
    delay::Delay, 
    peripherals::{Peripherals, I2C0}, 
    Blocking,
    prelude::*, 
    system::SystemControl, 
    gpio::{Io, Level, Output},
    i2c::I2C
};

const I2C_ADDR: u8 = 0x27; // LCD1602的I2C地址

// LCD 指令
const LCD_CMD_CLEAR: u8 = 0x01;
const LCD_CMD_HOME: u8 = 0x02;
const LCD_CMD_ENTRY_MODE: u8 = 0x04;
const LCD_CMD_DISPLAY_CONTROL: u8 = 0x08;
const LCD_CMD_FUNCTION_SET: u8 = 0x20;
const LCD_CMD_SET_DDRAM_ADDR: u8 = 0x80;

// LCD 控制位
const LCD_BACKLIGHT: u8 = 0x08;
const ENABLE: u8 = 0x04;
const RW_WRITE: u8 = 0x00;
const RS_DATA: u8 = 0x01;
const RS_COMMAND: u8 = 0x00;

#[entry]
fn main() -> ! {
    let peripherals = Peripherals::take();
    let system = SystemControl::new(peripherals.SYSTEM);

    let clocks = ClockControl::max(system.clock_control).freeze();
    let delay = Delay::new(&clocks);

    esp_println::logger::init_logger_from_env();

    // Set GPIO0 as an output, and set its state high initially.
    let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
    let mut led = Output::new(io.pins.gpio0, Level::High);

    // 初始化 I2C
    let mut i2c: I2C<I2C0, Blocking> = I2C::new(peripherals.I2C0, io.pins.gpio6, io.pins.gpio5, 400.kHz(), &clocks);
    log::info!("The type of i2c is: {}", core::any::type_name_of_val(&i2c));

    // 初始化 LCD
    lcd_init(&mut i2c);
    lcd_write_string(&mut i2c, "Hello, World!");

    loop {
        log::info!("Hello world! \n");
        led.toggle();
        delay.delay(500.millis());
    }
}

fn lcd_init(i2c: &mut I2C<I2C0, Blocking>) {
    // 设置 4-bit 模式
    lcd_command(i2c, 0x33); // 初始化指令
    lcd_command(i2c, 0x32); // 设置4-bit模式
    lcd_command(i2c, LCD_CMD_FUNCTION_SET | 0x08); // 2行显示
    lcd_command(i2c, LCD_CMD_DISPLAY_CONTROL | 0x0F); // 打开显示,有光标,会闪烁
    lcd_command(i2c, LCD_CMD_CLEAR); // 清屏
    lcd_command(i2c, LCD_CMD_ENTRY_MODE | 0x02); // 设置光标移动方向
}

fn lcd_command(i2c: &mut I2C<I2C0, Blocking>, command: u8) {
    lcd_write(i2c, command, RS_COMMAND);
}

fn lcd_data(i2c: &mut I2C<I2C0, Blocking>, data: u8) {
    lcd_write(i2c, data, RS_DATA);
}

fn lcd_write(i2c: &mut I2C<I2C0, Blocking>, data: u8, mode: u8) {
    let high_nibble = data & 0xF0;
    let low_nibble = (data << 4) & 0xF0;
    lcd_send_nibble(i2c, high_nibble | mode);
    lcd_send_nibble(i2c, low_nibble | mode);
}

fn lcd_send_nibble(i2c: &mut I2C<I2C0, Blocking>, nibble: u8) {
    // 发送高4位
    let data = nibble | LCD_BACKLIGHT;
    let _ = i2c.write(I2C_ADDR, &[data | ENABLE]);
    let _ = i2c.write(I2C_ADDR, &[data & !ENABLE]);
}

fn lcd_write_string(i2c: &mut I2C<I2C0, Blocking>, s: &str) {
    for c in s.chars() {
        lcd_data(i2c, c as u8);
    }
}
  • diagram.json
{
    "version": 1,
    "editor": "wokwi",
    "author": "WuFengSheng <469742978@qq.com>",
    "parts": [
        {
            "type": "board-esp32-c3-devkitm-1",
            "id": "esp",
            "top": 0.59,
            "left": 0.67,
            "attrs": {
                "flashSize": "16"
            }
        },
        {
            "type": "wokwi-led",
            "id": "led1",
            "top": -20,
            "left": -50,
            "attrs": {
                "color": "red"
            }
        },
        {
            "type": "wokwi-resistor",
            "id": "r1",
            "top": 50,
            "left": -54.5,
            "rotate": 90,
            "attrs": {}
        },
        {
            "type": "wokwi-lcd1602",
            "id": "lcd1",
            "top": 46,
            "left": 132.07,
            "attrs": {
                "pins": "i2c"
            }
        },
        {
            "type": "wokwi-vcc",
            "id": "vcc1",
            "top": 20,
            "left": 105,
            "attrs": {}
        }
    ],
    "connections": [
        [
            "esp:TX",
            "$serialMonitor:RX",
            "",
            []
        ],
        [
            "esp:RX",
            "$serialMonitor:TX",
            "",
            []
        ],
        [
            "esp:GND.4",
            "led1:C",
            "black",
            [
                "h0"
            ]
        ],
        [
            "led1:A",
            "r1:1",
            "green",
            [
                "v0"
            ]
        ],
        [
            "r1:2",
            "esp:0",
            "green",
            [
                "h0",
                "v38"
            ]
        ],
        [
            "vcc1:VCC",
            "lcd1:VCC",
            "red",
            [
                "v0"
            ]
        ],
        [
            "lcd1:GND",
            "esp:GND.8",
            "black",
            [
                "h0"
            ]
        ],
        [
            "lcd1:SDA",
            "esp:6",
            "green",
            [
                "h0"
            ]
        ],
        [
            "lcd1:SCL",
            "esp:5",
            "green",
            [
                "h0"
            ]
        ]
    ],
    "serialMonitor": {
        "display": "terminal",
        "convertEol": true
    }
}

编译项目命令

cd esp-rs-demo
# 默认 debug
cargo build
# 或指定 release
cargo build --release

运行模拟器

注: VSCode 需要安装 wokwi 插件

在这里插入图片描述

ESP32C3 烧录

espflash flash --monitor target/riscv32imc-unknown-none-elf/debug/esp-rs-demo

在这里插入图片描述

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部