嵌入式异步框架 Embassy 实例
以下是关于嵌入式异步框架 Embassy 的实用示例,涵盖常见外设操作、多任务协作和硬件交互场景。示例基于STM32和Raspberry Pi Pico等平台,使用Rust语言编写。
GPIO 控制
use embassy_stm32::gpio::{Input, Output, Pull, Speed};
use embassy_stm32::peripherals::PA5;
// 配置GPIO输出
async fn blink_led(pin: PA5) {
let mut led = Output::new(pin, Speed::Low);
loop {
led.set_high();
embassy_time::Timer::after_secs(1).await;
led.set_low();
embassy_time::Timer::after_secs(1).await;
}
}
中断处理
use embassy_stm32::exti::ExtiInput;
use embassy_stm32::gpio::Input;
// 配置外部中断
async fn button_interrupt(pin: impl Peripheral<P = impl InputPin>) {
let button = Input::new(pin, Pull::Up);
let mut exti = ExtiInput::new(button, EXTI0);
loop {
exti.wait_for_falling_edge().await;
defmt::println!("Button pressed!");
}
}
串口通信
use embassy_stm32::usart::{Uart, Config};
use embassy_stm32::peripherals::USART1;
// 异步串口回显
async fn uart_echo(usart: USART1, tx: impl Pin, rx: impl Pin) {
let mut uart = Uart::new(usart, tx, rx, Config::default());
let mut buf = [0; 8];
loop {
uart.read(&mut buf).await.unwrap();
uart.write(&buf).await.unwrap();
}
}
定时器PWM输出
use embassy_stm32::pwm::Pwm;
use embassy_stm32::time::hz;
// 配置PWM输出
async fn pwm_control(tim: impl Peripheral<P = impl PwmPin>) {
let mut pwm = Pwm::new(tim, hz(1000));
pwm.set_max_duty(1000);
loop {
for duty in 0..=1000 {
pwm.set_duty(duty);
embassy_time::Timer::after_millis(10).await;
}
}
}
SPI 数据传输
use embassy_stm32::spi::Spi;
use embassy_stm32::peripherals::SPI1;
// SPI读取传感器数据
async fn read_spi_sensor(spi: SPI1, sck: impl Pin, mosi: impl Pin, miso: impl Pin) {
let mut spi = Spi::new(spi, sck, mosi, miso, Config::default());
let mut buf = [0; 2];
loop {
spi.transfer(&mut buf).await.unwrap();
defmt::println!("Sensor value: {}", buf[0] as u16 | ((buf[1] as u16) << 8));
embassy_time::Timer::after_secs(1).await;
}
}
I2C 设备访问
use embassy_stm32::i2c::I2c;
use embassy_stm32::peripherals::I2C1;
// I2C读取温湿度传感器
async fn read_i2c_sensor(i2c: I2C1, sda: impl Pin, scl: impl Pin) {
let mut i2c = I2c::new(i2c, scl, sda, Config::default());
let mut buf = [0; 4];
loop {
i2c.write_read(0x40, &[0xE3], &mut buf).await.unwrap();
defmt::println!("Temperature: {}", f32::from_be_bytes(buf));
embassy_time::Timer::after_secs(2).await;
}
}
多任务协作
use embassy_executor::Spawner;
// 启动并发任务
#[embassy_executor::main]
async fn main(spawner: Spawner) {
spawner.spawn(blink_led()).unwrap();
spawner.spawn(button_interrupt()).unwrap();
spawner.spawn(uart_echo()).unwrap();
}
看门狗配置
use embassy_stm32::wdg::IndependentWatchdog;
// 初始化独立看门狗
async fn init_watchdog() {
let mut wdt = IndependentWatchdog::new(IWDG, 2_000_000);
wdt.start();
loop {
wdt.pet();
embassy_time::Timer::after_secs(1).await;
}
}
DMA 数据传输
use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::UartTx;
// 使用DMA的串口发送
async fn dma_uart_send(usart: USART1, tx: impl Pin, dma: impl Peripheral) {
let mut uart = UartTx::new(usart, tx, NoDma, Config::default());
let data = b"Hello DMA!\r\n";
loop {
uart.write(&data).await.unwrap();
embassy_time::Timer::after_secs(1).await;
}
}
ADC 采样
use embassy_stm32::adc::Adc;
use embassy_stm32::peripherals::ADC1;
// 多通道ADC采样
async fn read_adc(adc: ADC1, pin1: impl Pin, pin2: impl Pin) {
let mut adc = Adc::new(adc, &mut Delay);
let mut ch1 = adc.enable_pin(pin1);
let mut ch2 = adc.enable_pin(pin2);
loop {
let v1 = adc.read(&mut ch1).await.unwrap();
let v2 = adc.read(&mut ch2).await.unwrap();
defmt::println!("ADC1: {}, ADC2: {}", v1, v2);
embassy_time::Timer::after_millis(500).await;
}
}
定时器编码器模式
use embassy_stm32::timer::Encoder;
// 读取编码器值
async fn read_encoder(tim: impl TimerWithEncoder) {
let mut enc = Encoder::new(tim);
loop {
let count = enc.read_count();
defmt::println!("Encoder: {}", count);
embassy_time::Timer::after_millis(100).await;
}
}
USB CDC 虚拟串口
use embassy_stm32::usb::Driver;
use embassy_usb::class::cdc_acm;
// USB串口回显
async fn usb_cdc_echo(driver: Driver<'static>) {
let mut usb = embassy_usb::Builder::new(driver);
let mut class = cdc_acm::Builder::new().build(&mut usb);
usb.build().await;
let mut buf = [0; 64];
loop {
let n = class.read(&mut buf).await.unwrap();
class.write(&buf[..n]).await.unwrap()