Embassy实战:Rust嵌入式异步开发指南
嵌入式异步框架 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) { 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) { 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) { 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()