文章目录
- 第2课时:Rust基础语法(变量、数据类型、运算符)
-
- 一、课程目标
- 二、课程重难点
- 三、课程内容
-
- [3.1 Rust变量](#3.1 Rust变量)
-
- [3.1.1 变量声明规则](#3.1.1 变量声明规则)
- [3.1.2 不可变与可变性](#3.1.2 不可变与可变性)
- [3.1.3 变量阴影化(Shadowing)](#3.1.3 变量阴影化(Shadowing))
- [3.2 Rust核心数据类型](#3.2 Rust核心数据类型)
-
- [3.2.1 标量类型(重点)](#3.2.1 标量类型(重点))
- [3.2.2 复合类型(基础)](#3.2.2 复合类型(基础))
- [3.3 Rust运算符](#3.3 Rust运算符)
- [3.4 实战演示](#3.4 实战演示)
- 四、课堂示例(可直接复制运行)
- 五、课后作业(巩固练习)
- 六、课程总结
- 七、课程关键词(重点记忆)
- 八、课程回顾总结
- [上节课作业答案:Rust简介与环境搭建 - 实战作业代码及说明](#上节课作业答案:Rust简介与环境搭建 - 实战作业代码及说明)
第2课时:Rust基础语法(变量、数据类型、运算符)
一、课程目标
-
掌握Rust变量的定义、声明规则及可变性控制,贴合嵌入式开发场景规范
-
熟记Rust核心数据类型(标量、复合),明确不同类型在STM32开发中的用途
-
熟练运用各类运算符(算术、比较、逻辑等),能编写简单的运算逻辑
-
结合示例练习,规范Rust代码编写格式,规避基础语法错误
二、课程重难点
-
重点:变量的可变性与不可变性、核心数据类型用法、运算符优先级
-
难点:变量阴影化的理解与正确使用、复合数据类型(数组、元组)的实操
三、课程内容
3.1 Rust变量
3.1.1 变量声明规则
Rust变量声明使用let关键字,默认是不可变(immutable),这是Rust内存安全的基础,避免意外修改数据导致的异常(尤其适配嵌入式场景)。
语法格式:let 变量名: 数据类型 = 赋值;(数据类型可省略,Rust会自动推导)
3.1.2 不可变与可变性
-
不可变变量(默认):声明后无法修改值,适合不需要变化的数据(如外设地址、常量参数)。
-
可变变量:在
let后加mut关键字,声明后可修改值,适合需要动态变化的数据(如传感器采集值、计数器)。
3.1.3 变量阴影化(Shadowing)
用let关键字重新声明同名变量,新变量会覆盖旧变量,称为阴影化。与可变变量不同,阴影化可以改变数据类型,且旧变量不可再访问。
3.2 Rust核心数据类型
Rust数据类型分为两大类:标量类型(单个值)和复合类型(多个值组合),嵌入式开发中重点关注标量类型和简单复合类型。
3.2.1 标量类型(重点)
-
整数类型:按位数和符号划分,嵌入式常用
u8(无符号8位,适配GPIO电平)、i32(有符号32位,常用计算)、u32(无符号32位,计数器)。 -
浮点类型:
f32(单精度浮点)、f64(双精度浮点),用于传感器浮点数据(如温度、湿度)。 -
布尔类型:
bool,值为true或false,用于判断逻辑(如按键是否按下、外设是否就绪)。 -
字符类型:
char,单引号包裹,占4字节,用于简单字符显示(如串口打印字符)。
3.2.2 复合类型(基础)
-
元组(Tuple):固定长度,不同类型值的组合,语法:
let 元组名 = (值1, 值2, ...);,适合组合少量相关数据(如坐标、外设状态)。 -
数组(Array):固定长度,相同类型值的组合,语法:
let 数组名: [类型; 长度] = [值1, 值2, ...];,适合存储批量相同类型数据(如传感器采集的多组数据)。
3.3 Rust运算符
运算符用于对数据进行运算,按功能分为4类,重点掌握算术、比较、逻辑运算符,适配嵌入式数据处理场景。
-
算术运算符:
+(加)、-(减)、*(乘)、/(除)、%(取余),用于数值计算(如传感器数据换算)。 -
比较运算符:
==(等于)、!=(不等于)、>(大于)、<(小于)等,用于判断逻辑(如阈值对比)。 -
逻辑运算符:
&&(逻辑与)、||(逻辑或)、!(逻辑非),用于复杂判断(如多条件触发外设)。 -
赋值运算符:
=(赋值)、+=(加赋值)、-=(减赋值)等,用于变量赋值和更新。
3.4 实战演示
结合嵌入式场景,编写简单语法演示代码,验证变量、数据类型和运算符的使用。
四、课堂示例(可直接复制运行)
示例1:变量的不可变、可变性与阴影化
rust
// 不可变变量(默认)
let led_pin = 13; // STM32 LED引脚编号,不可修改
// led_pin = 14; // 报错:不可变变量无法修改
// 可变变量
let mut counter = 0; // 计数器,可修改
counter += 1;
println!("计数器值:{}", counter);
// 变量阴影化
let num = 5;
let num = num * 2; // 阴影化,改变值,类型不变
let num = num.to_string(); // 阴影化,改变类型(i32 → String)
println!("阴影化后的num:{}", num);
示例2:数据类型实操(贴合嵌入式)
rust
// 标量类型
let gpio_level: u8 = 1; // GPIO高电平(0低电平,1高电平)
let temperature: f32 = 25.5; // 温度传感器采集值(℃)
let is_key_pressed: bool = false; // 按键未按下
let serial_char: char = 'A'; // 串口发送字符
// 复合类型
let sensor_data = (25.5, 60.2); // 元组:(温度,湿度)
let led_states: [bool; 3] = [true, false, true]; // 数组:3个LED的状态
// 打印所有数据
println!("GPIO电平:{}", gpio_level);
println!("温度:{}℃", temperature);
println!("按键状态:{}", is_key_pressed);
println!("串口字符:{}", serial_char);
println!("传感器数据:(温度:{}℃,湿度:{}%)", sensor_data.0, sensor_data.1);
println!("LED状态:{:?}", led_states);
示例3:运算符实操(嵌入式数据处理)
rust
// 算术运算:传感器数据换算(ADC采集值→实际电压)
let adc_value: u16 = 1023; // ADC采集最大值(12位ADC)
let voltage: f32 = (adc_value as f32) * 3.3 / 4095.0; // 换算为3.3V电压
// 比较运算:阈值判断(温度超过30℃触发报警)
let temperature = 32.5;
let is_alarm = temperature > 30.0;
// 逻辑运算:多条件判断(按键按下且温度正常)
let is_key_pressed = true;
let is_temp_normal = temperature <= 30.0;
let can_operate = is_key_pressed && is_temp_normal;
println!("ADC采集电压:{:.2}V", voltage);
println!("是否触发温度报警:{}", is_alarm);
println!("是否可操作:{}", can_operate);
五、课后作业(巩固练习)
-
- 编写代码,声明1个不可变变量(存储STM32引脚编号)、1个可变变量(存储计数器),实现计数器自增3次并打印每次结果。
-
- 定义标量类型变量(u8、i32、f32、bool),分别赋值并打印;定义1个元组(存储传感器的温度、湿度、气压),1个数组(存储4个LED的状态),打印所有数据。
-
- 编写代码,实现ADC采集值(0-4095)换算为电压(0-3.3V),判断电压是否在1.0V-2.5V之间,打印换算结果和判断结论。
-
- 尝试使用变量阴影化,将一个整数变量转换为字符串变量,打印转换前后的类型(可借助
std::any::type_name函数)。
- 尝试使用变量阴影化,将一个整数变量转换为字符串变量,打印转换前后的类型(可借助
六、课程总结
-
核心知识点:变量的声明规则、可变性与阴影化;标量与复合数据类型的分类及嵌入式用途;各类运算符的用法及优先级。
-
实操重点:规范声明变量,根据场景选择不可变/可变变量;熟练使用常用数据类型,掌握运算符在嵌入式数据处理中的应用。
-
关键结论:Rust基础语法是后续嵌入式开发的核心,变量不可变性、强类型特性的设计,能提升嵌入式程序的安全性和稳定性。
七、课程关键词(重点记忆)
-
变量、let、mut、变量阴影化
-
标量类型、复合类型、数组、元组
-
算术运算符、比较运算符、逻辑运算符
-
嵌入式数据类型适配、Rust强类型
八、课程回顾总结
本课时作为Rust基础入门的核心内容,重点讲解了Rust基础语法中的变量、数据类型和运算符,为后续Rust嵌入式开发筑牢语法基础。课程开篇明确了变量的声明规则,强调Rust变量默认不可变的特性,这是Rust内存安全设计的重要体现,契合嵌入式开发对程序稳定性的要求,同时讲解了可变变量(mut关键字)和变量阴影化的用法,区分二者的差异,避免开发中出现语法错误。
数据类型部分,重点介绍了嵌入式开发中常用的标量类型和简单复合类型,明确了不同类型的适用场景,比如u8用于GPIO电平、f32用于传感器浮点数据、元组和数组用于组合相关数据,让学员能根据实际开发需求选择合适的数据类型。运算符部分,聚焦算术、比较、逻辑三类核心运算符,结合嵌入式数据处理场景(如ADC值换算、阈值判断)进行演示,帮助学员理解运算符的实际用途和优先级。
课程通过三个实操示例,将理论知识与实践结合,让学员直观感受Rust语法的特点,同时布置分层课后作业,巩固变量、数据类型和运算符的用法。本课时的难点的是变量阴影化的理解和复合数据类型的实操,学员需通过多练习,规范代码编写格式,规避基础语法错误。通过本课时的学习,学员已掌握Rust基础语法核心内容,具备编写简单Rust代码的能力,为后续所有权、函数等知识点的学习,以及STM32嵌入式实操奠定了坚实基础。
上节课作业答案:Rust简介与环境搭建 - 实战作业代码及说明
一、实战作业代码(可直接复制运行)
rust
// src/main.rs
fn main() {
// 打印作业标题
println!("STM32 Rust第1课时作业");
println!("======================");
// 打印Rust工具链版本信息(验证环境)
println!("当前Rust编译器版本:rustc 1.94.0");
println!("当前Cargo版本:cargo 1.94.0");
// 验证嵌入式工具链(STM32适配)
println!("\n嵌入式工具链验证:");
println!("适配STM32 Cortex-M3内核目标:thumbv7m-none-eabi");
println!("已安装工具:cargo-flash、cargo-embed、probe-rs");
// 模拟STM32开发板信息打印(贴合嵌入式场景)
println!("\nSTM32开发板信息:");
println!("开发板型号:STM32F103C8T6");
println!("内核:Cortex-M3");
println!("调试工具:ST-Link");
// 打印作业完成提示
println!("\n作业完成!环境搭建正常,可进入后续Rust语法学习。");
}
二、代码功能说明
本代码为第1课时实战作业核心代码,用于验证Rust工具链及STM32嵌入式适配环境是否搭建成功。代码首先打印作业标题及分隔线,清晰区分作业内容;随后打印Rust编译器和Cargo包管理器版本,直观验证基础环境安装有效性;接着验证STM32嵌入式工具链适配情况,明确标注适配的STM32内核目标及已安装的烧录、调试工具;最后模拟打印STM32开发板信息,贴合嵌入式学习场景,结尾给出作业完成提示。整体代码简洁易懂,无复杂逻辑,核心作用是验证环境,同时让学员熟悉Rust基础打印语法,为后续实操铺垫。
三、注意事项
-
- 运行代码前,需确保Rust工具链及STM32适配工具(cargo-flash、probe-rs等)已安装完成,环境变量生效。
-
- 代码运行命令为
cargo run,需在创建的Rust项目(如hello_rust)的src/main.rs文件中修改代码。
- 代码运行命令为
-
- 若运行时提示"命令未找到",需重启终端,确保环境变量完全生效,或手动执行环境生效命令。
-
- 可根据实际安装的Rust版本,修改代码中版本号,确保打印信息与实际一致。
-
- 若连接ST-Link调试器,可在代码中添加调试日志,进一步验证调试工具是否正常识别。