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/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

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/436867.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

可视化图表与源代码显示配置项及页面的动态调整功能分析

可视化图表与源代码显示配置项及页面的动态调整功能分析 文章目录 可视化图表与源代码显示配置项及页面的动态调整功能分析1.分析图表源代码2.分析源代码显示功能**完整代码参考&#xff1a;** 3.分析源代码显示及动态调整**完整代码参考&#xff1a;** 4.分析代码编辑器及运行…

中国电信解锁万亿参数大模型:TeleAI的创新与突破

首个由万卡集群训练出来的万亿参数大模型&#xff0c;已被一家央企解锁。 具体而言&#xff0c;为了推动纯国产人工智能的探索&#xff0c;带来这条新路径的正是中国电信人工智能研究院&#xff08;TeleAI&#xff09;。 该研究院由中国电信集团的CTO、首席科学家兼院长李学龙…

CSS中字体图标的使用

引言&#xff1a; 在网页设计当中&#xff0c;会有很多很简洁的图标&#xff0c;比如箭头&#xff0c;照相机&#xff0c;放大镜等 这些大概率都是使用字体图标来完成的&#xff0c;因为字体图标比较简洁高效&#xff0c;不会像图片一样需要向浏览器请求数据。那么字体图标该…

使用powershell的脚本报错:因为在此系统中禁止执行脚本

1.添加powershell功能环境&#xff1a; 2.启动powershell的执行策略 因为在此系统中禁止执行脚本。 set-executionpolicy unrestricted

Redis: 主从复制读写分离环境搭建

概述 Redis 的单机模式实际上就是在一个服务器上装了一个单节点的Redis通过简单的配置和简单的命令启动起来就可以使用这种搭建环境&#xff0c;不保证高可用的情况下&#xff0c;完全没有问题如果说你的项目必须要具备高可用&#xff0c;而且 Redis 也要提供更高的性能这个单…

【hot100-java】【寻找重复数】

技巧 使用字典&#xff0c;边记录边比较&#xff0c;有直接输出。 def findDuplicate(nums):seen {}for num in nums:if num in seen:return numseen[num] Truereturn None 可惜不是O(1) 二分查找 class Solution {public int findDuplicate(int[] nums) {int left0;int ri…

宝塔搭建nextcould 30docker搭建onlyoffic8.0

宝塔搭建nextcould 宝塔搭建nextcould可以参考这两个博文 我搭建的是30版本的nextcould&#xff0c;服务组件用的是下面这些&#xff0c;步骤是一样的&#xff0c;只是版本不一样而已 nginx 1.24.0 建议选择nginx&#xff0c;apache没成功。 MySQL 8.0以上都可以 php 8.2.…

Certbot自动申请并续期https证书

Certbot自动申请并续期https证书 一、 安装 Certbot&#xff1a;使用命令安装 Certbot&#xff1a; dnf install certbot python3-certbot-nginx获取 SSL 证书&#xff1a;运行 Certbot 命令来获取并安装 SSL 证书。 示例命令&#xff0c;替换其中的域名和路径信息&#xff1a…

jmeter-请求参数加密-MD5加密

方法1 &#xff1a;使用jmeter自带的函数助手digest Tool(工具)---Function Helper Dialog(函数助手对话框) 第一个参数是要md5加密的值&#xff0c;第二个参数是保存加密后值的变量 &#xff08; 此处变量是从txt文件导入的&#xff0c;所以使用的是${wd} &#xff09; …

Linux网络操作命令与函数全面总结

1. 引言 Linux作为服务器和开发平台&#xff0c;网络操作是其核心功能之一。本文旨在全面总结Linux系统中的网络操作方法&#xff0c;包括命令行工具和编程接口&#xff0c;帮助读者深入理解Linux网络管理的机制。 2. 命令行工具 2.1 ping 命令 ping 命令用于测试网络连接和…

基于投影滤波算法的rick合成地震波滤波matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 RICK合成地震波模型 4.2 投影滤波算法原理 5.完整工程文件 1.课题概述 基于投影滤波算法的rick合成地震波滤波matlab仿真。分别通过标准的滤波投影滤波以及卷积滤波投影滤波对合成地震剖面进行滤波…

基于Hive和Hadoop的共享单车分析系统

本项目是一个基于大数据技术的共享单车分析系统&#xff0c;旨在为用户提供全面的单车使用信息和深入的出行行为分析。系统采用 Hadoop 平台进行大规模数据存储和处理&#xff0c;利用 MapReduce 进行数据分析和处理&#xff0c;通过 Sqoop 实现数据的导入导出&#xff0c;以 S…

论文阅读 | HiDDeN网络架构

ECCV 2018 斯坦福-李飞飞团队 一、问题描述 受以下启发&#xff1a; 对抗性例子的发现&#xff1a;深度学习模型在图像识别任务中对微小的、难以察觉的输入扰动非常敏感&#xff0c;这些扰动可以导致模型错误分类图像。这一现象表明&#xff0c;神经网络可以在图像中编码信息&…

Python或R时偏移算法实现

&#x1f3af;要点 计算单变量或多变量时序距离&#xff0c;使用欧几里得、曼哈顿等函数量化不同时序差异。量化生成时序之间接近度相似性矩阵。使用高尔距离和堪培拉距离等相似度测量。实现最小方差匹配算法&#xff0c;绘制步进模式的图形表示。其他语言包算法实现。 &…

IP协议讲解

IP协议 IP协议的本质&#xff1a;提供一种能力&#xff0c;将数据跨网络从A主机传输到B主机 4位版本号(version): 指定IP协议的版本, 对于IPv4来说, 就是4. 4位头部长度(header length): IP头部的长度是多少个32bit, 也就是 length * 4 的字节数. 4bit表示最大 的数字是15, 因…

【数据结构初阶】排序算法(下)冒泡排序与归并排序

文章目录 4. 交换排序4. 1 冒泡排序 5. 归并排序6. 非比较排序6. 1 计数排序 5. 排序性能分析6. 排序算法复杂度及稳定度分析 4. 交换排序 交换排序基本思想: 所谓交换**&#xff0c;就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置**。 交换排序的特点是…

归并排序【C语言版-笔记】

目录 一、概念二、排序流程理解三、代码实现3.1主调函数3.2 merge函数 四、性能分析 一、概念 归并是一种算法思想&#xff0c;是将两个或两个一上的有序表合并成一个长度较大的有序表。若一开始无序表中有n个元素&#xff0c;可以把n个元素看作n个有序表&#xff0c;把它们两…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-27

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-27 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-27目录1. VisScience: An Extensive Benchmark for Evaluating K12 Educational Multi-modal Scientific Reasoning VisScience:…

java中的强软弱虚

在java中对象的引用有强、软、弱、虚四种&#xff0c;这些引用级别的区别主要体现在对象的生命周期、回收时机的不同。 文章目录 准备工作1. 设置内存2. 内存检测 强引用软引用弱引用虚引用 准备工作 1. 设置内存 为方便调试&#xff0c;将内存设置为16MB 依次点击菜单栏的R…

初识算法 · 双指针(1)

目录 前言&#xff1a; 双指针算法 题目一&#xff1a; ​编辑 题目二: 前言&#xff1a; 本文作为算法部分的第一篇文章&#xff0c;自然是少不了简单叭叭两句&#xff0c;对于算法部分&#xff0c;多刷是少不了&#xff0c;我们刷题从暴力过度到算法解法&#xff0c;自…