Rust嵌入式开发库pic32-hal的使用,PIC32微控制器硬件抽象层(HAL)驱动开发

pic32-hal

一个针对部分PIC32微控制器的硬件抽象层。

Crates.io docs.rs

这个crate在PAC crate实现的寄存器访问API基础上提供了一个薄的低级API。提供以下HAL功能:

  • 基本时钟控制,包括参考时钟发生器
  • GPIO
  • UART
  • USB
  • 访问MIPS核心计时器
  • DMA通道
  • I2C外设
  • SPI外设
  • 中断控制器
  • 外设引脚选择(PPS)
  • 10位模数转换器(ADC)
  • 定时器
  • 输出比较

部分模块实现了embedded-hal API,这样使用该API的设备驱动(如显示器驱动)可以访问PIC32外设。

所有功能都还在开发中。

示例代码

以下是一个使用pic32-hal进行GPIO控制的完整示例:

// 导入必要的crate
use pic32_hal as hal;
use embedded_hal::digital::v2::OutputPin;
use hal::pac;

// 主函数
fn main() -> ! {
    // 获取外设访问权限
    let dp = pac::Peripherals::take().unwrap();
    
    // 初始化系统时钟
    let clocks = hal::clock::Clocks::new(dp.OSC);
    
    // 配置GPIO
    let gpioa = hal::gpio::Gpio::new(dp.PORTA);
    
    // 将PA0配置为输出引脚
    let mut led = gpioa.pa0.into_output();
    
    loop {
        // 切换LED状态
        led.set_high().unwrap();
        hal::delay(clocks.sysclk().0 / 2);
        led.set_low().unwrap();
        hal::delay(clocks.sysclk().0 / 2);
    }
}

UART示例

下面是一个使用UART进行串口通信的示例:

use pic32_hal as hal;
use hal::pac;
use hal::uart;

fn main() -> ! {
    let dp = pac::Peripherals::take().unwrap();
    let clocks = hal::clock::Clocks::new(dp.OSC);
    
    // 初始化UART1
    let uart1 = uart::Uart::new(
        dp.UART1,
        115200.bps(),
        clocks,
    );
    
    // 发送字符串
    uart1.write(b"Hello, PIC32!\r\n").unwrap();
    
    loop {
        // 接收数据
        if let Ok(byte) = uart1.read() {
            // 回显接收到的数据
            uart1.write(&[byte]).unwrap();
        }
    }
}

完整ADC示例

下面是一个使用ADC进行模拟信号采集的完整示例:

use pic32_hal as hal;
use hal::pac;

fn main() -> ! {
    // 获取外设访问权限
    let dp = pac::Peripherals::take().unwrap();
    
    // 初始化系统时钟
    let clocks = hal::clock::Clocks::new(dp.OSC);
    
    // 初始化ADC模块
    let mut adc = hal::adc::Adc::new(dp.ADC, &clocks);
    
    // 配置ADC通道0
    let channel = hal::adc::Channel::new(0);
    
    loop {
        // 启动ADC转换
        let value = adc.read(&channel).unwrap();
        
        // 处理ADC采样值
        // ...
        
        // 简单延时
        hal::delay(clocks.sysclk().0 / 1000);
    }
}

安装

在项目目录中运行以下Cargo命令:

cargo add pic32-hal

或在Cargo.toml中添加以下行:

pic32-hal = "0.13.0"

许可证

MIT OR Apache-2.0


1 回复

Rust嵌入式开发库pic32-hal的使用指南

简介

pic32-hal是一个用于PIC32微控制器系列的硬件抽象层(HAL)库,它提供了访问PIC32微控制器外设的Rust接口。这个库是建立在embedded-hal标准之上的,使得开发者可以使用Rust进行PIC32微控制器的嵌入式开发。

主要特性

  • 支持多种PIC32微控制器型号
  • 提供GPIO、UART、SPI、I2C等常见外设的抽象
  • 基于embedded-hal标准实现
  • 中断处理支持
  • 时钟配置功能

使用方法

1. 添加依赖

首先在项目的Cargo.toml中添加依赖:

[dependencies]
pic32-hal = "0.1"  # 请使用最新版本
cortex-m = "0.7"
embedded-hal = "0.2"

2. 基本初始化

#![no_std]
#![no_main]

use pic32_hal::pac;
use pic32_hal::prelude::*;
use panic_halt as _;

#[entry]
fn main() -> ! {
    // 获取设备外设访问权
    let dp = pac::Peripherals::take().unwrap();
    
    // 初始化时钟
    let clocks = pic32_hal::clock::ClockSetup::new(dp.OSC, dp.DEVCFG)
        .sys_clock(80.mhz())
        .freeze();
    
    // 获取GPIO端口
    let mut ports = pic32_hal::gpio::Ports::new(dp.PORTS);
    
    // 配置LED引脚为输出
    let mut led = ports.ra0.into_output();
    
    loop {
        // 翻转LED状态
        led.toggle().unwrap();
        pic32_hal::delay::delay_ms(1000);
    }
}

3. GPIO使用示例

// 配置按钮输入和LED输出
let button = ports.rb4.into_input();
let mut led = ports.ra1.into_output();

loop {
    if button.is_high().unwrap() {
        led.set_high().unwrap();
    } else {
        led.set_low().unwrap();
    }
}

4. UART通信示例

// 初始化UART
let mut uart = pic32_hal::uart::Uart::new(
    dp.UART1,
    (ports.rb10.into_alternate(), ports.rb7.into_alternate()),
    pic32_hal::uart::Config::default()
        .baudrate(115200.bps())
        .clock(clocks),
);

// 发送数据
uart.write(b"Hello from PIC32!\r\n").unwrap();

// 接收数据
let mut buf = [0u8; 32];
let len = uart.read(&mut buf).unwrap();

5. 中断处理示例

use pic32_hal::interrupt;

// 定义中断处理函数
#[interrupt]
fn TIMER1() {
    // 中断处理逻辑
    unsafe {
        (*pac::TIMER1::ptr()).intr.clear_bit();
    }
}

// 在主函数中配置和启用中断
pic32_hal::interrupt::enable_interrupt(
    pic32_hal::interrupt::Interrupt::TIMER1,
    pic32_hal::interrupt::Priority::P3,
);

注意事项

  1. 确保你的PIC32芯片型号被该库支持
  2. 需要正确配置链接器脚本和内存布局
  3. 某些功能可能需要特定的硬件配置
  4. 中断处理需要小心管理共享资源

完整示例代码

以下是一个结合GPIO和UART功能的完整示例:

#![no_std]
#![no_main]

use pic32_hal::{pac, prelude::*};
use panic_halt as _;

#[entry]
fn main() -> ! {
    // 初始化外设
    let dp = pac::Peripherals::take().unwrap();
    let clocks = pic32_hal::clock::ClockSetup::new(dp.OSC, dp.DEVCFG)
        .sys_clock(80.mhz())
        .freeze();
    
    // 初始化GPIO
    let mut ports = pic32_hal::gpio::Ports::new(dp.PORTS);
    let mut led = ports.ra0.into_output();
    let button = ports.rb4.into_input();
    
    // 初始化UART
    let mut uart = pic32_hal::uart::Uart::new(
        dp.UART1,
        (ports.rb10.into_alternate(), ports.rb7.into_alternate()),
        pic32_hal::uart::Config::default()
            .baudrate(115200.bps())
            .clock(clocks),
    );
    
    // 发送欢迎消息
    uart.write(b"PIC32 Rust HAL Demo Started\r\n").unwrap();
    
    loop {
        // 读取按钮状态并控制LED
        if button.is_high().unwrap() {
            led.set_high().unwrap();
            uart.write(b"Button pressed\r\n").unwrap();
        } else {
            led.set_low().unwrap();
        }
        
        // 延时防止过于频繁的检测
        pic32_hal::delay::delay_ms(100);
    }
}

这个示例演示了如何同时使用GPIO和UART功能,实现按钮控制LED并通过串口发送状态信息的功能。

回到顶部