Rust嵌入式开发库stm32f4的使用,针对STM32F4系列微控制器的硬件抽象层与设备驱动支持
Rust嵌入式开发库stm32f4的使用,针对STM32F4系列微控制器的硬件抽象层与设备驱动支持
概述
stm32f4 crate提供了对STM32F4系列微控制器外设的自动生成API。该API使用svd2rust生成,包含经过修补的SVD文件,提供了广泛的类型安全支持。
使用方法
每个支持的设备都通过一个特性门控制,这样您只需编译您想要的设备。在您的Cargo.toml中添加:
[dependencies.stm32f4]
version = "0.16.0"
features = ["stm32f401"]
默认启用的rt
特性带来了对cortex-m-rt
的支持。要禁用,请在Cargo.toml中指定default-features = false
。
在代码中使用:
use stm32f4::stm32f401;
let mut peripherals = stm32f401::Peripherals::take().unwrap();
let gpioa = &peripherals.GPIOA;
gpioa.odr.modify(|_, w| w.odr0().set_bit());
支持的设备
模块 | 设备 |
---|---|
stm32f401 | STM32F401 |
stm32f405 | STM32F405, STM32F415 |
stm32f407 | STM32F407, STM32F417 |
stm32f410 | STM32F410 |
stm32f411 | STM32F411 |
stm32f412 | STM32F412 |
stm32f413 | STM32F413, STM32F423 |
stm32f427 | STM32F427, STM32F437 |
stm32f429 | STM32F429, STM32F439 |
stm32f446 | STM32F446 |
stm32f469 | STM32F469, STM32F479 |
完整示例代码
下面是一个使用stm32f4库控制STM32F401开发板LED的完整示例:
#![no_std]
#![no_main]
// 导入必要的库
use panic_halt as _;
use cortex_m_rt::entry;
use stm32f4::stm32f401;
#[entry]
fn main() -> ! {
// 获取外设访问权限
let dp = stm32f401::Peripherals::take().unwrap();
// 启用GPIOA时钟
dp.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
// 配置PA5引脚为输出模式 (LED引脚)
dp.GPIOA.moder.modify(|_, w| w.moder5().output());
loop {
// 切换LED状态
dp.GPIOA.odr.modify(|r, w| w.odr5().bit(!r.odr5().bit()));
// 简单延时
for _ in 0..1_000_000 {
cortex_m::asm::nop();
}
}
}
配套的Cargo.toml配置
[package]
name = "stm32f4-example"
version = "0.1.0"
edition = "2021"
[dependencies]
cortex-m = "0.7.6"
cortex-m-rt = "0.7.1"
panic-halt = "0.2.0"
stm32f4 = { version = "0.16.0", features = ["stm32f401", "rt"] }
[profile.release]
codegen-units = 1
debug = true
incremental = false
lto = true
opt-level = 's'
注意事项
- 确保选择正确的设备特性(如stm32f401)
- 需要配合cortex-m-rt使用中断处理
- 需要提供合适的panic处理(如panic-halt)
- 必须使用no_std和no_main属性
这个库提供了对STM32F4系列微控制器的全面支持,包括所有外设的寄存器级访问。通过类型安全的API,可以更安全地配置和使用微控制器的各种功能。
1 回复
Rust嵌入式开发库stm32f4的使用指南
概述
stm32f4
是Rust生态中针对STM32F4系列微控制器的硬件抽象层(HAL)和设备驱动支持库。它提供了对STM32F4系列芯片外设的直接访问能力,是Rust嵌入式开发的重要工具。
主要特性
- 提供对STM32F4全系列MCU的支持
- 类型安全的硬件抽象接口
- 零成本抽象(Zero-cost abstractions)
- 与
embedded-hal
兼容的驱动接口 - 支持DMA、中断等高级特性
使用方法
1. 添加依赖
在Cargo.toml
中添加:
[dependencies]
stm32f4 = "0.15.1" # 请使用最新版本
cortex-m = "0.7.6"
cortex-m-rt = "0.7.3"
2. 基本外设使用示例
#![no_std]
#![no_main]
use panic_halt as _;
use cortex_m_rt::entry;
use stm32f4::stm32f407; // 根据具体芯片型号选择
#[entry]
fn main() -> ! {
// 获取外设访问权
let peripherals = stm32f407::Peripherals::take().unwrap();
// 启用GPIOD时钟
peripherals.RCC.ahb1enr.modify(|_, w| w.gpioden().enabled());
// 配置PD12为推挽输出
peripherals.GPIOD.moder.modify(|_, w| w.moder12().output());
peripherals.GPIOD.otyper.modify(|_, w| w.ot12().push_pull());
// 点亮LED(假设PD12连接LED)
peripherals.GPIOD.bsrr.write(|w| w.bs12().set());
loop {}
}
3. 使用HAL抽象层
更推荐使用HAL抽象层,它提供了更高级的API:
use stm32f4xx_hal::{
prelude::*,
gpio::GpioExt,
stm32,
};
#[entry]
fn main() -> ! {
let dp = stm32::Peripherals::take().unwrap();
// 初始化GPIO
let gpioc = dp.GPIOC.split();
let mut led = gpioc.pc13.into_push_pull_output();
// 配置SysTick定时器
let mut delay = dp.TIM1.delay_ms(1.hz());
loop {
led.set_high();
delay.delay_ms(1000_u32);
led.set_low();
delay.delay_ms(1000_u32);
}
}
4. 使用中断
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m_rt::{entry, exception};
use stm32f4xx_hal::stm32;
#[exception]
fn SysTick() {
// 中断处理代码
}
#[entry]
fn main() -> ! {
let mut cp = cortex_m::Peripherals::take().unwrap();
let dp = stm32::Peripherals::take().unwrap();
// 配置SysTick中断
cp.SYST.set_clock_source(SystClkSource::Core);
cp.SYST.set_reload(8_000_000); // 1s中断
cp.SYST.enable_interrupt();
cp.SYST.enable_counter();
loop {}
}
常见外设驱动
1. UART通信示例
use stm32f4xx_hal::{
serial::{config::Config, Serial},
prelude::*,
};
let gpioa = dp.GPIOA.split();
let tx = gpioa.pa2.into_alternate_af7();
let rx = gpioa.pa3.into_alternate_af7();
let serial = Serial::usart2(
dp.USART2,
(tx, rx),
Config::default().baudrate(115200.bps()),
clocks,
).unwrap();
// 发送数据
block!(serial.write(b'H')).ok();
block!(serial.write(b'i')).ok();
2. PWM输出示例
use stm32f4xx_hal::{
pwm::PwmExt,
time::Hertz,
};
let gpioa = dp.GPIOA.split();
let pa8 = gpioa.pa8.into_alternate_af1();
let pwm = dp.TIM1.pwm(pa8, 1.khz(), clocks);
let max_duty = pwm.get_max_duty();
pwm.set_duty(max_duty / 2); // 50%占空比
pwm.enable();
开发建议
- 使用
probe-rs
和cargo-flash
进行烧录和调试 - 结合
defmt
日志框架进行调试输出 - 参考
embedded-hal
兼容的驱动生态 - 使用
cortex-m-rtfm
或RTIC
框架进行实时任务管理
完整示例代码
以下是一个完整的STM32F4 HAL使用示例,包含LED闪烁和UART输出功能:
#![no_std]
#![no_main]
use panic_halt as _;
use core::fmt::Write;
use cortex_m_rt::entry;
use stm32f4xx_hal::{
prelude::*,
stm32,
serial::{config::Config, Serial},
timer::Timer,
gpio::GpioExt,
};
#[entry]
fn main() -> ! {
// 获取设备外设
let dp = stm32::Peripherals::take().unwrap();
let cp = cortex_m::Peripherals::take().unwrap();
// 初始化时钟
let rcc = dp.RCC.constrain();
let clocks = rcc.cfgr.sysclk(84.mhz()).freeze();
// 初始化GPIO
let gpioa = dp.GPIOA.split();
let gpioc = dp.GPIOC.split();
// 配置LED引脚(PC13)
let mut led = gpioc.pc13.into_push_pull_output();
// 配置UART2(PA2为TX,PA3为RX)
let tx = gpioa.pa2.into_alternate_af7();
let rx = gpioa.pa3.into_alternate_af7();
let mut serial = Serial::usart2(
dp.USART2,
(tx, rx),
Config::default().baudrate(115200.bps()),
clocks,
).unwrap();
// 初始化SysTick定时器
let mut delay = Timer::syst(cp.SYST, &clocks).delay();
// 初始化计数器
let mut count = 0;
// 发送欢迎消息
writeln!(serial, "STM32F4 Rust HAL Demo\r").unwrap();
loop {
// 切换LED状态
led.toggle();
// 发送计数信息
writeln!(serial, "Count: {}\r", count).unwrap();
count += 1;
// 延迟1秒
delay.delay_ms(1000_u32);
}
}
这个完整示例展示了:
- 基本的时钟配置
- GPIO控制LED
- UART通信初始化
- 定时器延时
- 循环计数并通过UART输出
要运行此代码,需要根据实际硬件连接修改GPIO引脚配置,并确保正确配置了Cargo.toml依赖项。