嵌入式異步框架 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()