当前位置: 首页 > news >正文

Rust 语言开发 ESP32C3 并在 Wokwi 电子模拟器上运行(esp-hal 非标准库、LCD1602、I2C)

文章目录

  • esp-rs 简介
  • Github
  • Rust 包仓库
  • 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-buildRust 编译器 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/

Rust 教程

  • https://rustwiki.org/zh-CN/book/
  • https://rustwiki.org/zh-CN/rust-by-example/index.html

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]
#![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);// 初始化 I2Clet 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));// 初始化 LCDlcd_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

在这里插入图片描述

相关文章:

Rust 语言开发 ESP32C3 并在 Wokwi 电子模拟器上运行(esp-hal 非标准库、LCD1602、I2C)

文章目录 esp-rs 简介GithubRust 包仓库Rust 教程Wokwi 电子模拟器开发环境Rust 环境esp-rs 环境创建 ESP32C3 项目项目结构编译项目命令运行模拟器ESP32C3 烧录 esp-rs 简介 esp-rs 是一个专注于为 Espressif 系列芯片&#xff08;如 ESP32、ESP32-S2、ESP32-C3 等&#xff0…...

项目-坦克大战笔记-墙体销毁以及人机销毁

在子弹撞到墙或者人机身上时会将碰撞到的墙体或者人机销毁 我们需要做到几点 检测子弹碰撞到的墙体或者人机将物体获取到 每帧遍历墙体列表与人机列表&#xff0c;检测被碰撞的墙&#xff0c;创建一个方法返回值为对应类型将被碰撞的物体返回出来 public static gudin wallp…...

硬件设计-利用环路设计优化PLL的输出性能

目录 前言 问题描述 问题分析步骤 杂散源头排查 245.76M 参考相噪&#xff1a; 30.72M VCXO的相噪性能测试如下: 解决方案 前言 LMK04832是TI 新发布的低抖动双环去抖模拟时钟&#xff0c; 其最高输出频率可以到达3250MHz&#xff0c; 输出抖动极低&#xff0c;3200MHz…...

Vue入门-Node.js安装

进入Node.js中文网 ​​​​​​​点击进入Node.js中文网 或者手动输入网址&#xff1a; https://www.nodejs.com.cn/download.html 点击下载64位安装包&#xff1a; 下载好之后双击进行安装 可选择个性化安装或默认安装 直接点【Next】按钮&#xff0c;此处可根据个人需求…...

OpenCV threhold()函数

OpenCV threhold()函数的主要用途是将灰度图转换为二值图像,实现灰度图的二值化&#xff0c;在机器视觉中使用频度较高&#xff0c;如尺寸量测&#xff0c;物体识别等。其原型如下&#xff1a; 函数参数&#xff1a; src 输入数组&#xff08;多通道、8 位或 32 位浮点&#xf…...

Qt教程(002):Qt项目创建于框架介绍

二、创建Qt项目 2.1 创建项目 【1、New Project】 【2、选择Qt Widgets Application】 【3、设置项目名称和保存路径】 注意&#xff0c;项目名称和路径不要带中文。 【4、选择QWidget】 带菜单栏的窗口QMainWindow空白窗口QWidget对话框窗口QDialog 【5、编译】 2.2 项目框…...

《C++游戏人工智能开发:开启智能游戏新纪元》

在当今的游戏世界中&#xff0c;人工智能&#xff08;AI&#xff09;已经成为了不可或缺的一部分。它能够为游戏增添深度、挑战性和真实感&#xff0c;让玩家沉浸其中&#xff0c;享受前所未有的游戏体验。而对于 C开发者来说&#xff0c;如何在 C中实现高效的游戏人工智能开发…...

SPSS and Origin Paired Samples T-Test

SPSS https://www.spss-tutorials.com/spss-paired-samples-t-test/ Testing the Normality Assumption We can now test the normality assumption by running a Shapiro-Wilk test ora Kolmogorov-Smirnov test. Origin分析 两个软件计算的一样...

速成java记录(上)

简单学一下&#xff0c;要求不高&#xff0c;能看懂java代码就行。 &#xff08;太不容易了&#xff0c;已经好久没写博客了&#xff0c;希望以后可以坚持&#xff09; /*** 文档注释* Author zmj* Data 2024/10/5 15:46 下午* Version 1.0*/import java.util.Scanner;//输入…...

春秋云镜靶场之CVE-2022-28525

1.环境搭建 我们开启环境 可以看到题目提示我们是文件上传漏洞&#xff0c;那么我们就进行测试 2.开启环境 我们开启环境&#xff0c;可以看到是一个登录页面&#xff0c;登录页面:一种是弱口令&#xff0c;一种是自己进行注册&#xff0c;一种是SQL注入&#xff0c;一种是在…...

【LLM】Agent在智能客服的实践(AI agent、记忆、快捷回复 | ReAct)

note 内容概况&#xff1a;结合京粉app学习agent的实践 Agent架构&#xff1a;通过模型训练提升LLM识别工具的准确性&#xff1b;设计可扩展并安全可控的agent架构扩展业务能力。记忆&#xff1a;多轮对话应用中如何组织、存储和检索记忆来提升大模型对用户的理解。快捷回复&…...

19款奔驰E300升级新款触摸屏人机交互系统

《19 款奔驰 E300 的科技焕新之旅》 在汽车科技日新月异的时代&#xff0c;19 款奔驰 E300 的车主们为了追求更卓越的驾驶体验&#xff0c;纷纷选择对爱车进行升级改装&#xff0c;其中新款触摸屏人机交互系统的改装成为了热门之选。 19 款奔驰 E300 作为一款经典车型&#x…...

Python知识点:如何使用Spark与PySpark进行分布式数据处理

开篇&#xff0c;先说一个好消息&#xff0c;截止到2025年1月1日前&#xff0c;翻到文末找到我&#xff0c;赠送定制版的开题报告和任务书&#xff0c;先到先得&#xff01;过期不候&#xff01; Apache Spark 是一个强大的分布式数据处理系统&#xff0c;而 PySpark 是 Spark …...

低功耗4G模组Air780E之串口通信篇

你对低功耗4G模组Air780E有多少了解&#xff1f; 今天我们来讲解低功耗4G模组Air780E的串口通信的基本用法&#xff0c;小伙伴们&#xff0c;学起来吧&#xff01; 一、硬件准备 780E开发板一套&#xff0c;包括天线、USB数据线。 USB转TTL工具或线&#xff08;例如ch340、…...

Python | Leetcode Python题解之第455题分发饼干

题目&#xff1a; 题解&#xff1a; class Solution:def findContentChildren(self, g: List[int], s: List[int]) -> int:g.sort()s.sort()m, n len(g), len(s)i j count 0while i < m and j < n:while j < n and g[i] > s[j]:j 1if j < n:count 1i …...

交叠型双重差分法

交叠型双重差分法&#xff08;Staggered Difference-in-Differences, Staggered DiD&#xff09;是一种扩展的双重差分&#xff08;Difference-in-Differences, DiD&#xff09;方法&#xff0c;用于处理多个时间点的政策干预或处理组&#xff08;treatment group&#xff09;并…...

Java中的数据合并与拆分:使用Stream API实现数据的灵活处理

Java中的数据合并与拆分&#xff1a;使用Stream API实现数据的灵活处理 大家好&#xff0c;我是微赚淘客返利系统3.0的小编&#xff0c;是个冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;在Java开发中&#xff0c;数据处理是最基础的操作之一&#xff0c;而在面对…...

Arthas(阿尔萨斯)

Arthas Arthas可以为你做什么&#xff1f; 安装下载 //Linux环境下 wget https://alibaba.github.io/arthas/arthas-boot.jar //Windows环境下可以直接去官网下载压缩包 https://arthas.aliyun.com/doc/download.html//启动命令 java -jar arthas-boot.jar 启动阿尔萨斯&#…...

黑马linux笔记(转载)

学习链接 视频链接&#xff1a;黑马程序员新版Linux零基础快速入门到精通 原文链接&#xff1a;黑马程序员新版Linux零基础快速入门到精通——学习笔记 黑马Linux笔记 文章目录 学习链接01初识Linux1.1、操作系统概述1.1.1、硬件和软件1.1.2、操作系统1.1.3、常见操作系统 1.…...

SQL Server—通配符(模糊查询)详解

SQL Server—通配符(模糊查询)详解 在SQL Server中&#xff0c;通配符是一种特殊的符号&#xff0c;用于在LIKE运算符中搜索模式。SQL Server支持三种通配符&#xff1a;百分号&#xff08;%&#xff09;&#xff0c;下划线&#xff08;_&#xff09;和方括号&#xff08;[]&am…...

软考系统分析师知识点二:经济管理

前言 今年报考了11月份的软考高级&#xff1a;系统分析师。 考试时间为&#xff1a;11月9日。 倒计时&#xff1a;35天。 目标&#xff1a;优先应试&#xff0c;其次学习&#xff0c;再次实践。 复习计划第一阶段&#xff1a;扫平基础知识点&#xff0c;仅抽取有用信息&am…...

C语言自定义类型联合和枚举(25)

文章目录 前言一、联合体联合体的声明联合体的特点联合体和结构体内存布局对比联合体的大小计算联合体的实际使用样例礼品兑换单判断当前机器是大端还是小端 二、枚举枚举的定义枚举类型的声明枚举类型的优点枚举类型的使用 总结 前言 关于自定义类型除了我们常用的结构体&…...

Kafka 的重平衡问题详解及解决方案

引言 Kafka 是目前非常流行的分布式消息队列系统&#xff0c;被广泛应用于流数据处理、日志分析、事件驱动架构等场景中。Kafka 的高吞吐量和分布式架构在应对海量数据传输方面具有显著优势。然而&#xff0c;Kafka 在处理消费者组时&#xff0c;会面临一个核心问题——重平衡…...

比较GPT4比较正确的回复的提问方式和比较失败的提问方式之间的区别?

比较GPT4比较正确的回复的提问方式和比较失败的提问方式之间的区别&#xff1f; 正确提问失败提问异同 正确提问 ####一堆python源码############# 这里如何根据数据是新建还是更新来调用不同的save方法&#xff1f; 失败提问 ####一堆python源码############# 为什么在修改…...

jmeter学习(1)线程组与发送请求

1、线程组 执行顺序 &#xff1a;setUp线程组 > 线程组 > tearDown线程组 2、 发送请求 可以发送http、java、dubbo 请求等 下面讲解发送http 1&#xff09;Http请求默认值 作用范围是该线程组下的所有HTTP请求&#xff0c;如果http请求设置的与默认值冲突&#xff0…...

【小技巧】mysql 判断表字段是否存在 删除字段 sql脚本

MySQL 判断表字段是否存在 删除字段 sql脚本 下面是一个包含插入和更新操作的流程&#xff1a; -- 先尝试插入数据 INSERT IGNORE INTO user_info (last_name, first_name) VALUES (x, y);-- 如果插入成功&#xff0c;ROW_COUNT() 返回 1&#xff0c;否则返回 0 IF ROW_COUNT…...

低代码革命:重塑工业互联网的未来版图

在数字化转型的浪潮中&#xff0c;低代码应用正以前所未有的速度席卷各行各业&#xff0c;尤其是在工业互联网领域&#xff0c;它正悄然改变着企业的技术架构和业务模式。本文将深入探讨低代码应用如何成为工业互联网的技术趋势&#xff0c;并展望其未来的辉煌前景&#xff0c;…...

KNN算法

KNN算法 一 KNN算法介绍二 KNN算法API2.1 KNeighborsClassifier 分类算法2.2 KNeighborsRegressor 回归算法 三 两个经典案例3.1 鸢尾花案例3.2 手写数字识别案例 一 KNN算法介绍 K-近邻算法&#xff08;K Nearest Neighbor&#xff0c;简称KNN&#xff09;.比如根据你的“邻居…...

TS 中类型的继承

在 TypeScript&#xff08;TS&#xff09;中&#xff0c;类型的继承通常通过接口&#xff08;Interfaces&#xff09;和类&#xff08;Classes&#xff09;来实现。接口提供了一种定义对象形状的方式&#xff0c;而类则提供了一种创建对象实例的方式。以下是如何在 TypeScript …...

在VS code 中部署C#和avalonia开发环境

要在 Mac 的 VS Code 中配置 C# 和 Avalonia 的开发环境&#xff0c;您可以按照以下步骤进行&#xff1a; 1. 安装 .NET SDK 下载 .NET SDK&#xff1a; 访问 .NET 下载页面。选择适用于 macOS 的最新稳定版本的 .NET SDK&#xff0c;并下载安装程序。安装 .NET SDK&#xff1…...