Rust嵌入式开发库pic32mx2xx的使用,支持PIC32MX2xx系列微控制器的硬件抽象与驱动开发
Rust嵌入式开发库pic32mx2xx的使用,支持PIC32MX2xx系列微控制器的硬件抽象与驱动开发
简介
pic32mx2xx库为PIC32MX1xx/2xx系列微控制器(包括一些eXtreme Low Power (XLP)设备)提供了外设访问API。该库是通过edc2svd
和svd2rust
工具生成的。
使用方法
在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();
}
}
}
示例说明
- 首先导入必要的库,包括panic处理程序和pic32mx2xx库
- 根据选择的设备特性(如pic32mx2xxfxxxb)导入对应的设备模块
- 在main函数中获取设备外设实例
- 初始化系统时钟
- 获取GPIOA端口并将其配置为输出
- 在主循环中切换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();
}
}
}
注意事项
- 确保在Cargo.toml中选择正确的设备特性
- 项目需要设置为no_std和no_main
- 需要提供panic处理程序(如panic_halt)
- 根据实际硬件连接调整GPIO引脚
- 使用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
注意事项
- 该库仍在开发中,部分功能可能不完整
- 需要配合适当的链接脚本和启动代码
- 使用时需参考PIC32MX2xx系列的具体数据手册
- 某些高级功能可能需要直接访问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();
}
}
这个完整示例展示了如何:
- 初始化系统时钟
- 配置GPIO控制LED
- 设置UART通信
- 实现中断处理
- 结合主循环和中断处理实现完整功能
项目结构应该包含以下文件:
Cargo.toml
- 项目配置文件memory.x
- 链接脚本src/main.rs
- 主程序文件
构建和运行步骤与之前描述的相同。