硬件抽象层与设备驱动
学习使用硬件抽象层(HAL),并编写简单的设备驱动,与微控制器上的外设交互。
硬件抽象层与设备驱动 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 2 节课,共 3 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 3 节课。
硬件抽象层(HAL)
欢迎来到嵌入式 Rust 的世界!使用微控制器时,您会遇到一个重要概念:硬件抽象层(HAL)。
HAL 是一种软件层,为微控制器的 GPIO 引脚、I2C、SPI 和 UART 等外设提供标准化接口。它隐藏了直接操作寄存器时复杂繁琐的细节。
为什么需要 HAL
想象一下让 LED 闪烁的过程。在一种微控制器上,您可能需要设置寄存器 GPIO_PORTA_DR 中的某一位;而在另一种微控制器上,可能需要设置 PIND_OUT。
- 复杂性:直接访问寄存器既繁琐又容易出错。
- 可移植性:没有 HAL 时,为一种芯片编写的代码无法在另一种芯片上运行,即使它们属于同一系列。
HAL 通过提供一致的硬件交互方式解决了这一问题,无论底层使用哪种芯片都一样。
Rust 的嵌入式 HAL 生态
在 Rust 中,embedded-hal crate 定义了一组用于常见外设操作的特征(类似接口)。这些特征充当契约,具体的微控制器 HAL 必须实现它们。
embedded-hal:提供通用特征(例如DigitalOutputPin、I2c)。- 特定芯片的 HAL:例如
rp-hal(用于 Raspberry Pi Pico)或stm32f4xx-hal,会针对各自的硬件实现这些特征。
这种分离方式使设备驱动程序能够以通用方式编写!
HAL 基本交互:GPIO
下面看看 HAL 如何抽象通用输入/输出(GPIO)引脚。在实际的嵌入式代码中,您会从芯片的 HAL 获取引脚对象并进行配置。
此示例模拟您如何与一个“引脚”对象交互来控制 LED。
struct GpioPin {
name: String,
state: bool,
}
impl GpioPin {
fn new(name: &str) -> Self {
println!("Configuring {} as output...", name);
GpioPin { name: name.to_string(), state: false }
}
fn set_high(&mut self) {
self.state = true;
println!("{} set to HIGH (LED ON)", self.name);
}
fn set_low(&mut self) {
self.state = false;
println!("{} set to LOW (LED OFF)", self.name);
}
fn toggle(&mut self) {
if self.state { self.set_low(); } else { self.set_high(); }
}
}
fn main() {
let mut led_pin = GpioPin::new("LED_GPIO_PIN");
println!("\n--- Blinking LED Simulation ---");
led_pin.set_high();
led_pin.set_low();
led_pin.toggle();
led_pin.toggle();
println!("-----------------------------");
}理解 GPIO 引脚模式
GPIO 引脚不只是用于开关设备!它们有不同的模式:
- 输出:用于控制外部组件(例如 LED)。
- 输入:用于读取外部组件(例如按钮)发出的信号。
- 带上拉/下拉的输入:在没有连接任何设备时确保状态稳定,防止输入端“悬空”。
- 模拟:用于读取连续的电压值(例如来自传感器的电压)。
HAL 提供了安全配置这些模式的方法。
什么是设备驱动程序?
HAL 为您提供对外设的底层控制,而设备驱动程序则构建在 HAL 之上,为特定的外部设备(例如温度传感器、LCD 屏幕)提供更高级的功能。
设备驱动程序抽象了通信协议(例如 I2C 或 SPI)以及特定芯片所需的具体命令,将原始字节传输转换为 sensor.read_temperature() 这样有意义的操作。
使用 `embedded-hal` 统一驱动程序
embedded-hal 真正的强大之处,在于编写驱动程序时才能充分体现。驱动程序不必了解某个 STM32 或 RP2040 所使用的具体 HAL,而只需要了解 embedded-hal trait。
例如,I2C temperature 传感器的驱动程序可能要求传入一个实现了 embedded_hal::i2c::I2c trait 的对象。这意味着,任何具有实现了该 trait 的 HAL 的微控制器,都可以使用同一份驱动程序代码!
驱动程序示例:I2C 传感器(概念)
假设您有一个通过 I2C 通信的 temperature 传感器。它的设备驱动程序可以:
- 接收一个
embedded_hal::i2c::I2c对象作为输入。 - 实现
read_temperature()或set_config()等方法。 - 在内部,通过
embedded-haltrait 使用底层 HAL 提供的i2c.write_read()或i2c.write()方法。
这样就为传感器创建了一个简洁且可复用的接口。
创建基本驱动程序的步骤
如果您想为新的组件编写一个简单的设备驱动程序,可以参考以下概念性步骤:
- 定义驱动程序结构体:保存外设接口(例如 HAL 的 I2C 对象)以及驱动程序特有的状态。
- 实现 `new()`:初始化驱动程序,并根据需要配置外设。
- 添加交互方法:创建
read_data()、write_config()等使用 HAL 方法的函数。 - 处理错误:使用 Rust 的
Result类型,以平稳地处理通信或设备错误。
HAL 与驱动程序快速检查
测试您对硬件抽象层和设备驱动程序的理解。
回顾:HAL 与驱动程序
在本课中,我们探讨了硬件抽象层(HAL)如何提供关键的抽象层,从而简化与微控制器外设的交互,并增强代码的可移植性。
我们还学习了设备驱动程序如何基于 HAL 和 embedded-hal trait 构建,为特定外部组件提供高级且可复用的接口,让您无需处理底层通信细节。这种分层方式是构建健壮的嵌入式 Rust 程序的关键!
用 AI 导师学习 Rust — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 39
- 课程
- 144
常见问题解答
「硬件抽象层与设备驱动」课时是免费的吗?
是的 — 「硬件抽象层与设备驱动」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 3 节课。
「硬件抽象层与设备驱动」这节课中我会学到什么?
学习使用硬件抽象层(HAL),并编写简单的设备驱动,与微控制器上的外设交互。 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Learn Rust Coding 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 3 节。
「硬件抽象层与设备驱动」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Learn Rust Coding 课中编写并运行代码吗?
能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 嵌入式 Rust 入门
- 硬件抽象层与设备驱动
- 操作系统开发概念