米菲爸爸

  • 2025-04-01
  • 回复了主题帖: 动手实践任务二 使用fs接口,read等trait打印文本文件的每行数据

    秦天qintian0303 发表于 2025-4-1 11:45 打印是通过串口回传的吗?   编辑的时候显示都正常一发布就乱套了

  • 发表了主题帖: 动手实践任务三 基于serial库开发单片机串口下载工具(上) - 嵌入式rust环境配置

    本帖最后由 米菲爸爸 于 2025-4-3 00:36 编辑 本次学习中的任务三才是嵌入式rust学习的真正开始,坑由此才开始出现。本文以windows环境下安装配置为例 首先,我们为了搭建普通的rust环境都会选择稳定版本 原安装地址 curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 因为众所周知的原因这个方便比较慢而且容易断,所以我们使用阿里云的源来替换 # 使用阿里云安装脚本 curl --proto '=https' --tlsv1.2 -sSf https://mirrors.aliyun.com/repo/rust/rustup-init.sh | sh 增加全局变量   RUSTUP_UPDATE_ROOT    https://mirrors.aliyun.com/rustup/rustup RUSTUP_DIST_SERVER    https://mirrors.aliyun.com/rustup   配置 crates.io 镜像 在 Rust 生态系统中,crates.io 是官方的 crate 仓库,它存储了大量的 Rust 库和工具。 为了让 cargo 知道有哪些可用的 crate 以及它们的版本信息,crates.io 维护了一个索引(index)。 这个索引本质上是一个包含了所有 crate 元数据的数据库,cargo 通过查询这个索引来了解 crate 的相关信息,进而进行依赖解析和下载。 传统的 cargo 索引是一个完整的 Git 仓库,每次更新索引时,cargo 需要克隆或拉取整个 Git 仓库,这会消耗大量的时间和磁盘空间,尤其是对于大型项目或者网络较慢的情况。 为了解决这个问题,Rust 引入了 sparse 协议。 sparse 索引是一种更轻量级的索引格式,它允许 cargo 只下载它实际需要的 crate 元数据,而不是整个索引仓库。 这样可以显著减少下载时间和磁盘空间的使用。 registry = "sparse+https:..." 表示使用 sparse 协议通过 HTTPS 来访问指定的 crate 索引。其中 sparse+ 是协议前缀,用于告诉 cargo 使用 sparse 索引格式,后面的 https://... 是具体的索引服务器地址。   在 cargo 配置文件: ~/.cargo/config.toml 中,添加以下内容: (Windows 系统配置文件地址默认为:%USERPROFILE%\.cargo\config.toml 也就是C:\Users\YourUsername\.cargo\config.toml 目前该镜像仅支持稀疏索引配置,需要您的 cargo 版本 >=1.68。) 这里选择阿里云的源 [source.crates-io] replace-with = 'aliyun' [source.aliyun] registry = "sparse+https://mirrors.aliyun.com/crates.io-index/" 当然如果你对阿里云有什么成见的话也可以选择使用中科大的源 [source.crates-io] replace-with = 'ustc' [source.ustc] registry = "sparse+https://mirrors.ustc.edu.cn/crates.io-index"   安装完rust以后你以为你就可以开发嵌入式rust了么? 但......是......嵌入式rust开发目前需要安装rust nightly版本 rustup default nightly 这一步也是需要从网络下载的 D:\code\Rust>rustup default nightly info: syncing channel updates for 'nightly-x86_64-pc-windows-msvc' info: latest update on 2025-03-29, rust version 1.87.0-nightly (920d95eaf 2025-03-28) info: downloading component 'cargo' 8.5 MiB / 8.5 MiB (100 %) 2.7 MiB/s in 3s ETA: 0s info: downloading component 'clippy' 3.6 MiB / 3.6 MiB (100 %) 2.9 MiB/s in 1s ETA: 0s info: downloading component 'rust-docs' 19.9 MiB / 19.9 MiB (100 %) 3.9 MiB/s in 5s ETA: 0s info: downloading component 'rust-std' 22.6 MiB / 22.6 MiB (100 %) 3.5 MiB/s in 7s ETA: 0s info: downloading component 'rustc' 73.7 MiB / 73.7 MiB (100 %) 3.9 MiB/s in 20s ETA: 0s info: downloading component 'rustfmt' info: installing component 'cargo' info: installing component 'clippy' info: installing component 'rust-docs' 19.9 MiB / 19.9 MiB (100 %) 2.2 MiB/s in 17s ETA: 0s info: installing component 'rust-std' 22.6 MiB / 22.6 MiB (100 %) 6.9 MiB/s in 3s ETA: 0s info: installing component 'rustc' 73.7 MiB / 73.7 MiB (100 %) 8.4 MiB/s in 8s ETA: 0s info: installing component 'rustfmt' info: default toolchain set to 'nightly-x86_64-pc-windows-msvc' nightly-x86_64-pc-windows-msvc installed - rustc 1.87.0-nightly (920d95eaf 2025-03-28) 嵌入式编译工具链 rustup target list 安装 Cortex-M0 编译工具(Py32_Rust_Dev_1.1) rustup target add thumbv6m-none-eabi 安装Probe-rs cargo install cargo-binstall cargo binstall probe-rs-tools cargo install cargo-binstall 这一步需要大概15分钟,如果没有阿里云加速的话需要科学上网    

  • 发表了日志: 动手实践任务二 使用fs接口,read等trait打印文本文件的每行数据

  • 发表了主题帖: 动手实践任务二 使用fs接口,read等trait打印文本文件的每行数据

    本帖最后由 米菲爸爸 于 2025-4-1 17:59 编辑 在Rust里,trait 是一种定义共享行为的方式,它能让你指定类型必须实现的一组方法。 可以把 trait 看作是其他编程语言里的接口,但又有一些区别。下面详细介绍 trait 的相关内容: 1. 定义trait 使用 trait 关键字来定义一个 trait,下面是一个简单的示例: // 定义一个名为 Summary 的 trait trait Summary { fn summarize(&self) -> String; } 在这个例子中,Summary 这个 trait 定义了一个方法 summarize,任何实现 Summary trait 的类型都必须实现这个方法。 2. 实现trait 为自定义类型实现 trait 可以使用 impl 关键字,示例如下: // 定义一个结构体 struct NewsArticle { headline: String, location: String, author: String, content: String, } // 为 NewsArticle 结构体实现 Summary trait impl Summary for NewsArticle { fn summarize(&self) -> String { format!("{}, by {} ({})", self.headline, self.author, self.location) } } fn main() { let article = NewsArticle { headline: String::from("Penguins win the Stanley Cup Championship!"), location: String::from("Pittsburgh, PA, USA"), author: String::from("Iceburgh"), content: String::from("The Pittsburgh Penguins once again are the best hockey team in the NHL."), }; println!("{}", article.summarize()); } 3. 默认实现 Trait 可以为方法提供默认实现,实现该 trait 的类型可以选择使用默认实现或者自定义实现。 trait Summary { fn summarize(&self) -> String { String::from("(Read more...)") } } struct NewsArticle { // ... } impl Summary for NewsArticle {} fn main() { let article = NewsArticle {}; println!("{}", article.summarize()); // 输出: (Read more...) } 4. trait 作为参数和返回值  Trait 可以用作函数的参数和返回值,这样函数就能接受实现了特定 trait 的任意类型。 trait Summary { fn summarize(&self) -> String; } // trait 作为参数 fn notify(item: &impl Summary) { println!("Breaking news! {}", item.summarize()); } // trait 作为返回值 fn returns_summarizable() -> impl Summary { struct Tweet { username: String, content: String, } impl Summary for Tweet { fn summarize(&self) -> String { format!("{}: {}", self.username, self.content) } } Tweet { username: String::from("horse_ebooks"), content: String::from("of course, as you probably already know, people"), } } 总结来说,trait 是 Rust 中实现多态和代码复用的重要工具,它允许你定义类型之间的共同行为,并在不同类型上使用统一的接口。   此任务没有什么太多可以说的,直接代码贴上 use std::fs::File; use std::io::{BufRead, BufReader}; fn main() { // 打开文件 let file = File::open("Cargo.toml").expect("无法打开文件"); // 创建一个 BufReader 来逐行读取文件 let reader = BufReader::new(file); // 逐行读取文件并打印每行内容 for line in reader.lines() { match line { Ok(line) => println!("{}", line), Err(e) => eprintln!("读取行时出错: {}", e), } } } 在当前选中的代码里,虽然没有显式定义 trait,但隐式地使用了多个 trait。 1. File::open 方法 let file = File::open("Cargo.toml").expect("无法打开文件"); 现了 std::fmt::Debug trait,所以才能在 expect 方法里使用错误信息。 expect 方法要求 Err 变体实现 Debug trait,这样才能将错误信息格式化输出。 2. BufReader::new 方法 let reader = BufReader::new(file); BufReader::new 接收一个实现了 std::io::Read trait 的类型作为参数。File 类型实现了 Read trait,所以能作为参数传递给 BufReader::new。 3. reader.lines() 方法 for line in reader.lines() { // ... } lines() 方法返回一个迭代器,该迭代器产生 Result<String, std::io::Error> 类型的值。这里涉及到 std::io::BufRead trait,BufReader 实现了 BufRead trait,而 lines() 方法正是 BufRead trait 定义的方法。 4. println! 和 eprintln! 宏 Ok(line) => println!("{}", line), Err(e) => eprintln!("读取行时出错: {}", e),  println! 和 eprintln! 宏要求参数实现 std::fmt::Display trait。String 类型实现了 Display trait,所以可以直接用 println! 打印;std::io::Error 类型也实现了 Display trait,因此能通过 eprintln! 输出错误信息。  

  • 2025-03-25
  • 加入了学习《直播回放: 嵌入式Rust入门基础知识、解析动手实战Rust的三个任务》,观看 嵌入式Rust入门基础知识、解析动手实战Rust的三个任务

  • 加入了学习《直播回放: 嵌入式Rust入门基础知识、解析动手实战Rust的三个任务》,观看 答疑内容

  • 2025-03-20
  • 回复了主题帖: 动手实践任务一 使用冒泡排序处理数组并打印

    jobszheng5 发表于 2025-3-20 11:22 我觉得您就坚持 Python 就得了。 直接玩嵌入式的高性能板卡就行了,低端的也没有太多的意义 嗯,是,我也是借这个事情顺手把rust捡一捡,我现在目标是如果后面rust嵌入式过于专业了我就放弃。我也确实不打算往高性能嵌入式这个方向上走太远,了解为主,回头还是去搞wasm路稍宽一点

  • 2025-03-19
  • 回复了主题帖: 动手实践任务一 使用冒泡排序处理数组并打印

    jobszheng5 发表于 2025-3-19 22:49 又学习RUST去了啊! 您这还真有想法 原来就会这个,但是前一段没用手生了。最近看还能开发嵌入式就来试试。说到底是我对C++就强烈偏见只要能不用C++的办法我都有兴趣

  • 发表了日志: 动手实践任务一 使用冒泡排序处理数组并打印

  • 发表了主题帖: 动手实践任务一 使用冒泡排序处理数组并打印

    本帖最后由 米菲爸爸 于 2025-3-21 20:07 编辑 函数 bubble_sort 是一个经典的冒泡排序算法实现。 冒泡排序的基本思想是,对于数组中的相邻元素,如果前一个元素大于后一个元素,就交换它们的位置。 这样一轮下来,最大的元素就会"冒泡"到数组的末尾。重复这个过程,直到整个数组有序。   1 函数接收一个可变的i32类型数组切片作为参数 2 首先获取数组的长度n 3 使用双重循环进行排序:     外层循环(i)控制排序的轮数,每轮会将当前最大的元素"冒泡"到正确的位置     内层循环(j)进行相邻元素的比较和交换,范围从0到n-i-1,因为每轮结束后最后的i个元素已经有序 4 如果发现前一个元素大于后一个元素(arr[j] > arr[j+1]),就交换它们的位置 5 最终,数组会按从小到大的顺序排列 这个算法的时间复杂度是O(n²),空间复杂度是O(1)。虽然它不是最高效的排序算法,但实现简单,适合教学和小规模数据排序。   // 冒泡排序函数,可变引用(&mut) :arr 是一个可变引用 可以修改传入的数组 在Rust中,可变引用(&mut)是一个非常重要的概念,它允许你在不转移所有权的情况下修改数据。 1 基本概念:     可变引用使用 &mut 语法     它允许你借用数据并对其进行修改     同时确保内存安全 2 特点:     可变性:可以修改引用的数据     独占性:在同一个作用域内,只能有一个可变引用     临时性:引用只在作用域内有效 3 与不可变引用的区别:     不可变引用(&)只允许读取数据     可变引用(&mut)允许读取和修改数据 4 使用场景:     当需要修改数据但不想转移所有权时     在函数参数中传递需要修改的数据     在需要高效修改大型数据结构时 5 内存安全保证:     Rust编译器会确保不会同时存在可变引用和不可变引用     防止数据竞争   fn bubble_sort(arr: &mut [i32]) { let n = arr.len(); for i in 0..n { for j in 0..n-i-1 { if arr[j] > arr[j+1] { arr.swap(j, j+1); } } } } fn main() { let mut numbers = [64, 34, 25, 12, 22, 11, 90]; println!("排序前: {:?}", numbers); bubble_sort(&mut numbers); println!("排序后: {:?}", numbers); }  

  • 2025-03-12
  • 回复了主题帖: 嵌入式Rust修炼营入围名单来啦,一起度过嵌入式Rust学习时光的小伙伴集合啦~

    个人信息无误

  • 回复了主题帖: 嵌入式Rust修炼营入围名单来啦,一起度过嵌入式Rust学习时光的小伙伴集合啦~

    初、中、高

  • 2025-03-10
  • 回复了主题帖: 嵌入式Rust修炼营:动手写串口烧录工具和MCU例程,Rust达人Hunter直播带你入门Rust

    参与理由&个人编程基础: -学习rust在嵌入式的编程,时间比较充裕可以学到高级。个人二十年软件工程师,rust有涉猎旦无嵌入式工程实践 -Rust学习过程第一个坑点是系统环境配置,我已经过了这关并且有视频产出。 【【Rust 初体验】 Part1 Rust 入门-哔哩哔哩】 https://b23.tv/WVFnARd 第二个难点是内存权限管理,这个需要加强学习

  • 2025-02-23
  • 回复了主题帖: 颁奖:验证并选择心仪MOSFET,探寻选型奥秘!注册、体验双重好礼等你拿~

    确认个人信息无误

  • 2024-12-20
  • 发表了主题帖: 【嵌入式AI挑战营,进阶】微雪幸狐Pico Max开发板 】配网 安装包 算管脚 点灯

    本帖最后由 米菲爸爸 于 2024-12-21 08:40 编辑 切换开发板静态ip(非必要) ifconfig usb0 192.168.137.2   增加路由 route add default gw 172.32.0.100   修改启动增加路由 vim /etc/rc.local   测试网络 ping www.baidu.com   备份sources.list sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak   编辑sources.list sudo vim /etc/apt/sources.list   更新apt sudo apt-get update && sudo apt-get upgrade   给pip增加全局清华的源 pip config set global.index-url http://pypi.tuna.tsinghua.edu.cn/simple   安装包 pip install python-periphery   pin脚计算公式,举例右下角的pin脚GPIO2_A4_d #GPIO 引脚编号计算公式:pin = bank * 32 + number #GPIO 组内编号计算公式:number = group * 8 + X #综上:pin = bank * 32 + (group * 8 + X)   #GPIO2_A4_d bank = 2  # group = 0 #(A=0, B=1, C=2, D=3) X = 4 pin = bank * 32 + (group * 8 + X)   本人不擅长文字,后面补上  

  • 发表了主题帖: 【嵌入式AI挑战营,进阶】微雪幸狐Pico Max开发板 开箱 烧固件 SSH连接 开发环境

    本人不擅长文字,后面补上  

  • 2024-11-22
  • 回复了主题帖: 入围名单公布:嵌入式工程师AI挑战营(进阶)的挑战者们,领取板卡啦

    个人信息已确认,领取板卡,可继续完成任务

  • 2024-11-17
  • 回复了主题帖: 嵌入式工程师AI挑战营(进阶):在RV1106部署InsightFace算法的多人实时人脸识别实战

    跟帖申请; 申请理由: 1.InsightFace 简述     InsightFace 和yolo类似都是是一个开源的人脸识别算法,用于人脸检测、对齐和特征提取,具备高精度和高性能的特点,相较于yolo更适合在资源受限的设备上使用。 2.在 RV1106 上部署实现思路     InsightFace 需根据 RV1106 的计算能力和 NPU 兼容性选择轻量化的模型。使用 Rockchip 提供的工具链,将模型转换为 RV1106 可运行的格式,并优化性能过程类似于openvino。先定位人脸,然后判断人脸属于谁。尽量优化推理效率,使系统能够识别多个人脸。 3.打算部署的应用     基于 RV1106 和 InsightFace,实现一个实时多人拍照系统。配合双舵机可以实现人像自动居中,自动识别身份,并在图像上显示姓名标注并拍照。

最近访客

< 1/2 >

统计信息

已有20人来访过

  • 芯积分:56
  • 好友:--
  • 主题:5
  • 回复:9

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言