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'

注意事项

  1. 确保选择正确的设备特性(如stm32f401)
  2. 需要配合cortex-m-rt使用中断处理
  3. 需要提供合适的panic处理(如panic-halt)
  4. 必须使用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();

开发建议

  1. 使用probe-rscargo-flash进行烧录和调试
  2. 结合defmt日志框架进行调试输出
  3. 参考embedded-hal兼容的驱动生态
  4. 使用cortex-m-rtfmRTIC框架进行实时任务管理

完整示例代码

以下是一个完整的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);
    }
}

这个完整示例展示了:

  1. 基本的时钟配置
  2. GPIO控制LED
  3. UART通信初始化
  4. 定时器延时
  5. 循环计数并通过UART输出

要运行此代码,需要根据实际硬件连接修改GPIO引脚配置,并确保正确配置了Cargo.toml依赖项。

回到顶部