Rust嵌入式开发库pic32mx2xx的使用,支持PIC32MX2xx系列微控制器的硬件抽象与驱动开发

Rust嵌入式开发库pic32mx2xx的使用,支持PIC32MX2xx系列微控制器的硬件抽象与驱动开发

简介

pic32mx2xx库为PIC32MX1xx/2xx系列微控制器(包括一些eXtreme Low Power (XLP)设备)提供了外设访问API。该库是通过edc2svdsvd2rust工具生成的。

使用方法

在Cargo.toml中添加以下依赖,并选择对应的设备特性:

[dependencies.pic32mx2xx]
version = "0.7.0"
features = ["pic32mx2xxfxxxb", "rt"]

支持的设备

模块/特性 设备
pic32mx1xxfxxxb 28引脚PIC32MX1xx
pic32mx1xxfxxxc 36引脚PIC32MX1xx
pic32mx1xxfxxxd 44引脚PIC32MX1xx
pic32mx2xxfxxxb 28引脚PIC32MX2xx
pic32mx2xxfxxxc 36引脚PIC32MX2xx
pic32mx2xxfxxxd 44引脚PIC32MX2xx
pic32mx1x4fxxxb 28引脚PIC32MX1xx XLP
pic32mx1x4fxxxd 44引脚PIC32MX1xx XLP
pic32mx2x4fxxxb 28引脚PIC32MX2xx XLP
pic32mx2x4fxxxd 44引脚PIC32MX2xx XLP

完整示例代码

以下是一个使用pic32mx2xx库的完整示例,展示了如何初始化微控制器和使用GPIO:

// 导入必要的库
#![no_std]
#![no_main]

use panic_halt as _;
use pic32mx2xx as pac;

// 使用PIC32MX2xxFxxxB设备
#[cfg(feature = "pic32mx2xxfxxxb")]
use pac::pic32mx2xxfxxxb as pac_device;

// 入口函数
#[cortex_m_rt::entry]
fn main() -> ! {
    // 获取设备外设实例
    let dp = pac_device::Peripherals::take().unwrap();
    
    // 初始化系统时钟配置
    let _clocks = dp.OSCCTRL.constrain().freeze();
    
    // 获取GPIOA端口
    let gpioa = dp.GPIOA.split();
    
    // 配置RA0引脚为输出
    let mut led = gpioa.ra0.into_push_pull_output();
    
    loop {
        // 切换LED状态
        led.toggle();
        
        // 简单延时
        for _ in 0..1_000_000 {
            cortex_m::asm::nop();
        }
    }
}

示例说明

  1. 首先导入必要的库,包括panic处理程序和pic32mx2xx库
  2. 根据选择的设备特性(如pic32mx2xxfxxxb)导入对应的设备模块
  3. 在main函数中获取设备外设实例
  4. 初始化系统时钟
  5. 获取GPIOA端口并将其配置为输出
  6. 在主循环中切换LED状态并实现简单延时

扩展示例:使用UART通信

以下是一个扩展示例,展示如何使用pic32mx2xx库进行UART通信:

#![no_std]
#![no_main]

use core::fmt::Write;
use panic_halt as _;
use pic32mx2xx as pac;

#[cfg(feature = "pic32mx2xxfxxxb")]
use pac::pic32mx2xxfxxxb as pac_device;

// 导入hal库提供的UART抽象
use embedded_hal::serial::Write as SerialWrite;

#[cortex_m_rt::entry]
fn main() -> ! {
    // 获取外设实例
    let dp = pac_device::Peripherals::take().unwrap();
    
    // 配置时钟
    let clocks = dp.OSCCTRL.constrain().freeze();
    
    // 获取GPIO端口
    let gpioa = dp.GPIOA.split();
    
    // 配置UART引脚
    let tx_pin = gpioa.ra1.into_alternate_function();
    let rx_pin = gpioa.ra0.into_alternate_function();
    
    // 初始化UART1
    let uart = dp.UART1.uart(
        (tx_pin, rx_pin),
        embedded_hal::serial::config::Config::default()
            .baudrate(115200.bps()),
        &clocks,
    ).unwrap();
    
    // 分割发送和接收
    let (mut tx, _rx) = uart.split();
    
    loop {
        // 通过UART发送消息
        writeln!(tx, "Hello from PIC32MX2xx!\r").unwrap();
        
        // 延时
        for _ in 0..5_000_000 {
            cortex_m::asm::nop();
        }
    }
}

注意事项

  1. 确保在Cargo.toml中选择正确的设备特性
  2. 项目需要设置为no_std和no_main
  3. 需要提供panic处理程序(如panic_halt)
  4. 根据实际硬件连接调整GPIO引脚
  5. 使用UART等外设时需要正确配置时钟和引脚复用功能

这个扩展示例展示了如何使用pic32mx2xx库进行UART通信,你可以在此基础上继续扩展其他功能,如定时器、PWM、ADC等。


1 回复

Rust嵌入式开发库pic32mx2xx使用指南

概述

pic32mx2xx是一个用于PIC32MX2xx系列微控制器的Rust硬件抽象层(HAL)和驱动开发库。它为PIC32MX270/272/274/275/280/320/340/360/420/440/460等微控制器提供了类型安全的硬件接口抽象。

主要特性

  • 提供PIC32MX2xx系列微控制器的外设抽象
  • 支持GPIO、UART、SPI、I2C等常用接口
  • 中断处理支持
  • 时钟配置管理
  • 内存安全的外设访问

使用方法

1. 添加依赖

在Cargo.toml中添加依赖:

[dependencies]
pic32mx2xx = "0.1"
cortex-m = "0.7"
cortex-m-rt = "0.7"

2. 基本硬件初始化

#![no_std]
#![no_main]

use cortex_m_rt::entry;
use pic32mx2xx::pac;
use pic32mx2xx::prelude::*;

#[entry]
fn main() -> ! {
    // 获取外设访问权
    let dp = pac::Peripherals::take().unwrap();
    
    // 配置系统时钟
    let clocks = dp.SYSTEM.constrain()
        .oscillator()
        .use_primary()
        .pll_freq(80.mhz())
        .freeze();
    
    // 配置GPIO
    let mut gpio = dp.GPIO.split();
    let mut led = gpio.ra0.into_push_pull_output();
    
    loop {
        led.set_high().unwrap();
        cortex_m::asm::delay(clocks.sysclk().0 / 2);
        led.set_low().unwrap();
        cortex_m::asm::delay(clocks.sysclk().0 / 2);
    }
}

3. UART示例

use pic32mx2xx::serial::{Serial, Config};

// 初始化UART
let tx = gpio.rb10.into_alternate_function();
let rx = gpio.rb11.into_alternate_function();

let mut serial = Serial::uart1(
    dp.UART1,
    (tx, rx),
    Config::default()
        .baudrate(115200.bps())
        .parity_none()
        .stopbits(1),
    clocks,
);

// 发送数据
serial.write(b"Hello, PIC32MX2xx!\r\n").unwrap();

// 接收数据
let mut buf = [0u8; 32];
if let Ok(count) = serial.read(&mut buf) {
    // 处理接收到的数据
}

4. 中断处理

use cortex_m::peripheral::NVIC;
use pic32mx2xx::interrupt;

// 启用UART中断
serial.listen(interrupt::Event::RxNotEmpty);

// 在中断向量表中注册处理函数
#[interrupt]
fn UART1() {
    // 处理UART中断
    if let Ok(byte) = serial.read() {
        // 处理接收到的字节
    }
}

// 在main函数中启用中断
unsafe {
    NVIC::unmask(interrupt::UART1);
}

5. SPI通信示例

use pic32mx2xx::spi::{Spi, Mode, Phase, Polarity};

// 初始化SPI
let sck = gpio.rb14.into_alternate_function();
let sdo = gpio.rb11.into_alternate_function();
let sdi = gpio.rb13.into_alternate_function();

let mut spi = Spi::spi1(
    dp.SPI1,
    (sck, sdo, sdi),
    Mode {
        polarity: Polarity::IdleLow,
        phase: Phase::CaptureOnFirstTransition,
    },
    1.mhz(),
    clocks,
);

// SPI传输
let write = [0x01, 0x02, 0x03];
let mut read = [0u8; 3];
spi.transfer(&mut read, &write).unwrap();

构建与链接

需要为PIC32MX2xx目标配置链接脚本。在项目根目录创建memory.x文件:

MEMORY
{
    FLASH : ORIGIN = 0x1D000000, LENGTH = 128K
    RAM : ORIGIN = 0x00000000, LENGTH = 32K
}

_stack_start = ORIGIN(RAM) + LENGTH(RAM);

构建命令:

cargo build --target mipsel-unknown-none

注意事项

  1. 该库仍在开发中,部分功能可能不完整
  2. 需要配合适当的链接脚本和启动代码
  3. 使用时需参考PIC32MX2xx系列的具体数据手册
  4. 某些高级功能可能需要直接访问PAC层寄存器

完整示例

下面是一个完整的PIC32MX2xx项目示例,结合了GPIO控制、UART通信和中断处理:

#![no_std]
#![no_main]
#![feature(used)]

use cortex_m::asm;
use cortex_m_rt::entry;
use cortex_m_semihosting::hprintln;
use panic_halt as _;

use pic32mx2xx::{
    interrupt,
    pac,
    prelude::*,
    serial::{Config, Serial},
};

#[entry]
fn main() -> ! {
    // 获取外设实例
    let dp = pac::Peripherals::take().unwrap();
    
    // 配置时钟
    let clocks = dp.SYSTEM.constrain()
        .oscillator()
        .use_primary()
        .pll_freq(80.mhz())
        .freeze();
    
    // 配置GPIO
    let mut gpio = dp.GPIO.split();
    
    // 配置LED引脚
    let mut led = gpio.ra0.into_push_pull_output();
    
    // 配置UART引脚
    let tx = gpio.rb10.into_alternate_function();
    let rx = gpio.rb11.into_alternate_function();
    
    // 初始化UART
    let mut serial = Serial::uart1(
        dp.UART1,
        (tx, rx),
        Config::default()
            .baudrate(115200.bps())
            .parity_none()
            .stopbits(1),
        &clocks,
    );
    
    // 启用UART接收中断
    serial.listen(interrupt::Event::RxNotEmpty);
    
    // 启用中断
    unsafe {
        cortex_m::peripheral::NVIC::unmask(interrupt::UART1);
    }
    
    // 主循环
    loop {
        // 发送消息
        serial.write(b"PIC32MX2xx is running!\r\n").unwrap();
        
        // 翻转LED状态
        led.toggle().unwrap();
        
        // 延时
        asm::delay(clocks.sysclk().0 / 4);
    }
}

// UART中断处理函数
#[interrupt]
fn UART1() {
    // 获取外设实例
    let dp = unsafe { pac::Peripherals::steal() };
    
    // 处理接收到的数据
    if let Ok(byte) = Serial::uart1_read(&dp.UART1) {
        // 回显接收到的字节
        Serial::uart1_write(&dp.UART1, byte).unwrap();
    }
}

这个完整示例展示了如何:

  1. 初始化系统时钟
  2. 配置GPIO控制LED
  3. 设置UART通信
  4. 实现中断处理
  5. 结合主循环和中断处理实现完整功能

项目结构应该包含以下文件:

  • Cargo.toml - 项目配置文件
  • memory.x - 链接脚本
  • src/main.rs - 主程序文件

构建和运行步骤与之前描述的相同。

回到顶部