文章目录
- esp-rs 简介
- Github
- Rust 包仓库
- Wokwi 电子模拟器
- 开发环境
- Rust 环境
- esp-rs 环境
- 创建 ESP32C3 项目
- 项目结构
- 编译项目命令
- 运行模拟器
- ESP32C3 烧录
 
esp-rs 简介
esp-rs 是一个专注于为 Espressif 系列芯片(如 ESP32、ESP32-S2、ESP32-C3 等)提供 Rust 语言支持的社区和项目。它的目标是为开发者提供一个高效、安全且易于使用的 Rust 开发环境,以便在 Espressif 芯片上进行嵌入式系统开发。
- 构建工具
| 存储库 | 描述 | 
|---|---|
| esp-rs/rust | 带有 Xtensa 支持的 Rust 编译器分支 | 
| esp-rs/rust-build | Rust 编译器 fork 的预构建二进制文件以及安装脚本 | 
- 硬件抽象层
| 存储库 | 描述 | 
|---|---|
| esp-rs/esp-idf-hal | 支持 Rust 标准库(std) | 
| esp-rs/esp-hal | 不支持 Rust 标准库 ( no_std) | 
Github
- esp-rs:https://github.com/esp-rs
- esp-hal 非标准库:https://github.com/esp-rs/esp-hal
- 本章示例项目源码:https://github.com/WuFengSheng/esp-rs-demo
Rust 包仓库
- https://crates.io/
Wokwi 电子模拟器
- https://wokwi.com/projects/410182337086340097

开发环境
Rust 环境
- 参考我的这篇文章 《使用 Rustup 管理 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]
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;
    i2c.write(I2C_ADDR, &[data | ENABLE]);
    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








![[spring]用MyBatis XML操作数据库 其他查询操作 数据库连接池 mysql企业开发规范 动态sql](https://i-blog.csdnimg.cn/direct/f2b12158898c4aec9f16b03f8f0f30c2.png)











