Rust嵌入式开发库rp-pico的使用:专为树莓派Pico微控制器设计的硬件抽象与驱动支持

Rust嵌入式开发库rp-pico的使用:专为树莓派Pico微控制器设计的硬件抽象与驱动支持

rp-pico是一个为Raspberry Pi Pico微控制器板设计的Rust嵌入式开发库,它基于RP2040芯片,提供了硬件抽象层(HAL)和引脚配置支持。

使用方式

在Cargo.toml中添加依赖:

rp-pico = "0.9.0"

在程序中需要调用rp_pico::Pins::new来创建一个新的Pins结构,这将设置所有GPIO引脚。

示例项目搭建

创建一个新项目并添加必要的依赖:

cargo new project-name
cd project-name
cargo add rp-pico
cargo add cortex-m-rt
cargo add panic-halt

还需要从rp-hal-boards仓库复制.cargo/config文件和memory.x文件到项目根目录。

完整示例代码

以下是内容中提供的最简单工作示例:

#![no_std]
#![no_main]
use rp_pico::entry;
use panic_halt as _;

#[entry]
fn see_doesnt_have_to_be_called_main() -> ! {
    loop {}
}

这是一个最基本的框架程序,它只是无限循环而不做任何操作。

更多功能示例

内容中提到的几个示例功能:

  1. pico_blinky - 闪烁Pico板载LED
  2. pico_gpio_in_out - 读取GPIO 15上的按钮状态并控制板载LED
  3. pico_rtic - 演示在Pico上使用RTIC框架
  4. pico_countdown_blinky - 使用定时器的倒计时模式控制LED闪烁
  5. pico_pwm_blink - 在GPIO 25上输出模拟三角波
  6. pico_pwm_servo - 控制微型伺服电机
  7. pico_usb_serial - 创建USB串口设备
  8. pico_usb_serial_interrupt - 带中断处理的USB串口
  9. pico_usb_twitchy_mouse - 模拟USB鼠标输入设备
  10. pico_spi_sd_card - 使用SPI接口与SD卡通信

完整示例demo

以下是一个完整的LED闪烁示例(pico_blinky):

#![no_std]
#![no_main]
// 禁用标准库并指定无main函数的入口

use panic_halt as _; // 使用简单的panic处理
use rp_pico::entry;
use rp_pico::hal::gpio::Pin;
use rp_pico::hal::pac;
use rp_pico::hal::prelude::*;
use rp_pico::Pins;

#[entry]
fn main() -> ! {
    let mut pac = pac::Peripherals::take().unwrap(); // 获取RP2040外设
    let core = pac::CorePeripherals::take().unwrap(); // 获取ARM Cortex-M0+核心外设

    // 初始化时钟系统
    let mut watchdog = rp_pico::hal::Watchdog::new(pac.WATCHDOG);
    let clocks = rp_pico::hal::clocks::init_clocks_and_plls(
        rp_pico::XOSC_CRYSTAL_FREQ,
        pac.XOSC,
        pac.CLOCKS,
        pac.PLL_SYS,
        pac.PLL_USB,
        &mut pac.RESETS,
        &mut watchdog,
    )
    .ok()
    .unwrap();

    // 初始化延迟
    let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz());

    // 初始化GPIO引脚
    let pins = Pins::new(
        pac.IO_BANK0,
        pac.PADS_BANK0,
        pac.SIO.gpio_bank0,
        &mut pac.RESETS,
    );

    // 配置板载LED引脚(GPIO25)为输出
    let mut led_pin = pins.led.into_push_pull_output();

    // 主循环 - LED闪烁
    loop {
        led_pin.set_high().unwrap(); // 点亮LED
        delay.delay_ms(500); // 延迟500ms
        led_pin.set_low().unwrap(); // 熄灭LED
        delay.delay_ms(500); // 延迟500ms
    }
}

编译和运行示例

要编译示例:

rp-hal-boards/boards/rp-pico $ cargo build --release --example <name>

要转换为UF2格式并自动复制到板子:

rp-hal-boards/boards/rp-pico $ cargo run --release --example <name>

许可证

rp-pico采用双许可证:MIT OR Apache-2.0

贡献

欢迎贡献代码,具体步骤包括:

  1. Fork项目
  2. 创建特性分支
  3. 进行修改
  4. 提交变更
  5. 推送分支
  6. 创建Pull Request
  7. 等待审核和合并

1 回复

Rust嵌入式开发库rp-pico的使用指南

概述

rp-pico是一个专为树莓派Pico微控制器设计的Rust硬件抽象层(HAL)和驱动支持库。它提供了对RP2040微控制器的全面支持,使开发者能够使用Rust语言进行树莓派Pico的嵌入式开发。

主要特性

  • 完整的RP2040微控制器外设支持
  • 基于embedded-hal标准的硬件抽象
  • 丰富的驱动程序生态系统
  • 友好的Rust API设计
  • 支持Pico开发板的各种功能

使用方法

1. 添加依赖

在Cargo.toml中添加rp-pico作为依赖:

[dependencies]
rp-pico = "0.9.0"
rp2040-hal = "0.9.0"

2. 基本设置示例

以下是一个简单的LED闪烁示例:

#![no_std]
#![no_main]

use rp_pico::entry;
use rp_pico::hal::{
    clocks::{init_clocks_and_plls, Clock},
    pac,
    sio::Sio,
    watchdog::Watchdog,
};
use embedded_hal::digital::v2::OutputPin;
use panic_halt as _;

#[entry]
fn main() -> ! {
    let mut pac = pac::Peripherals::take().unwrap();
    let core = pac::CorePeripherals::take().unwrap();
    let mut watchdog = Watchdog::new(pac.WATCHDOG);
    let sio = Sio::new(pac.SIO);

    // 外部时钟为12MHz
    let external_xtal_freq_hz = 12_000_000u32;
    let clocks = init_clocks_and_plls(
        external_xtal_freq_hz,
        pac.XOSC,
        pac.CLOCKS,
        pac.PLL_SYS,
        pac.PLL_USB,
        &mut pac.RESETS,
        &mut watchdog,
    )
    .ok()
    .unwrap();

    let pins = rp_pico::Pins::new(
        pac.IO_BANK0,
        pac.PADS_BANK0,
        sio.gpio_bank0,
        &mut pac.RESETS,
    );

    let mut led_p极in = pins.led.into_push_pull_output();
    
    loop {
        led_pin.set_high().unwrap();
        cortex_m::asm::delay(1_000_000);
        led_pin.set_low().unwrap();
        cortex_m::asm::delay(1_000_000);
    }
}

3. 外设使用示例

GPIO输入输出

use rp_pico::hal::gpio::{Pin, PullUpInput, PushPullOutput};
use rp_pico::hal::prelude::*;

// 配置GPIO25为输出
let mut output_pin: Pin<_, PushPullOutput> = pins.gpio25.into_push_pull_output();

// 配置GPIO15为输入(上拉)
let input_pin: Pin<_, PullUpInput> = pins.gpio15.into_pull_up_input();

UART通信

use rp_pico::hal::uart::{UartConfig, DataBits, StopBits, Parity, UartPeripheral};

let uart = UartPeripheral::new(
    pac.UART0,
    &mut pac.RESETS,
    clocks.peripheral_clock.into(),
)
.enable(
    UartConfig::new(115200.0, DataBits::Eight, None, StopBits::One),
    clocks.peripheral_clock.into(),
)
.unwrap();

uart.write_full_blocking(b"Hello, Pico!\n");

PWM输出

use rp_pico::hal::pwm::{Pwm, FreeRunning, Channel, A, B};

let pwm = Pwm::new(pac.PWM0, &mut pac.RESETS);
let mut channel_a = pwm.channel_a.pin(pins.gpio0.into_mode::<A>());
let mut channel_b = pwm.channel_b.pin(pins.gpio1.into_mode::<B>());

pwm.set_divider(1.0);
channel_a.set_duty(32768);  // 50%占空比
channel_b.set_duty(16384);  // 25%占空比

4. 中断处理

use rp_pico::hal::pac::interrupt;
use cortex_m::interrupt::free as interrupt_free;

#[interrupt]
fn TIMER_IRQ_0() {
    interrupt_free(|cs| {
        // 中断处理代码
    });
}

构建和部署

  1. 安装必要的工具链:
rustup target add thumbv6m-none-eabi
cargo install elf2uf2-rs
  1. 构建项目:
cargo build --release
  1. 将程序刷写到Pico:
cargo run --release

注意事项

  • 确保项目配置为no_std
  • 需要正确设置内存布局(linker script)
  • 对于复杂项目,考虑使用cortex-m-rt提供的宏和功能
  • 调试可以使用probe-rs或其他支持的工具

完整示例代码

以下是一个结合多种功能的完整示例,展示了如何使用rp-pico库实现LED控制、UART通信和PWM输出:

#![no_std]
#![no_main]

use rp_pico::entry;
use rp_pico::hal::{
    clocks::{init_clocks_and_plls, Clock},
    gpio::{Pin, PushPullOutput},
    pac,
    pwm::{Pwm, Channel, A, B},
    sio::Sio,
    uart::{UartConfig, DataBits, StopBits, UartPeripheral},
    watchdog::Watchdog,
};
use embedded_hal::digital::v2::OutputPin;
use panic_halt as _;

#[entry]
fn main() -> ! {
    // 初始化外设
    let mut pac = pac::Peripherals::take().unwrap();
    let core = pac::CorePeripherals::take().unwrap();
    let mut watchdog = Watchdog::new(pac.WATCHDOG);
    let sio = Sio::new(pac.SIO);

    // 配置时钟
    let external_xtal_freq_hz = 12_000_000u32;
    let clocks = init_clocks_and_plls(
        external_xtal_freq_hz,
        pac.XOSC,
        pac.CLOCKS,
        pac.PLL_SYS,
        pac.PLL_USB,
        &mut pac.RESETS,
        &mut watchdog,
    )
    .ok()
    .unwrap();

    // 初始化GPIO
    let pins = rp_pico::Pins::new(
        pac.IO_BANK0,
        pac.PADS_BANK0,
        sio.gpio_bank0,
        &mut pac.RESETS,
    );

    // LED控制
    let mut led_pin = pins.led.into_push_pull_output();
    
    // UART初始化
    let uart = UartPeripheral::new(
        pac.UART0,
        &mut pac.RESETS,
        clocks.peripheral_clock.into(),
    )
    .enable(
        UartConfig::new(115200.0, DataBits::Eight, None, StopBits::One),
        clocks.peripheral_clock.into(),
    )
    .unwrap();

    // PWM初始化
    let pwm = Pwm::new(pac.PWM0, &mut pac.RESETS);
    let mut channel_a = pwm.channel_a.pin(pins.gpio0.into_mode::<A>());
    let mut channel_b = pwm.channel_b.pin(pins.gpio1.into_mode::<B>());
    pwm.set_divider(1.0);
    channel_a.set_duty(32768);  // 50%占空比
    channel_b.set_duty(16384);  // 25%占空比

    // 主循环
    let mut counter = 0;
    loop {
        // LED闪烁
        led_pin.set_high().unwrap();
        cortex_m::asm::delay(500_000);
        led_pin.set_low().unwrap();
        cortex_m::asm::delay(500_000);
        
        // UART发送计数
        counter += 1;
        uart.write_full_blocking(b"Counter: ");
        uart.write_full_blocking(itoa::Buffer::new().format(counter).as_bytes());
        uart.write_full_blocking(b"\n");
        
        // 调整PWM占空比
        channel_a.set_duty((counter % 65535) as u16);
    }
}

这个完整示例展示了:

  1. 系统初始化和时钟配置
  2. LED控制实现闪烁效果
  3. UART通信用于输出调试信息
  4. PWM输出控制
  5. 综合应用的主循环逻辑

要运行此示例,需要在Cargo.toml中添加额外的依赖:

[dependencies]
itoa = "1.0"
回到顶部