You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Embassy Rust中实现STM32L0定时器中断及资料查询方法

问题与需求
  • 核心需求:实现STM32L0上基于Embassy框架的定时器中断逻辑,同时掌握嵌入式Rust+Embassy环境下自行查找中断相关信息的有效途径
  • 背景:接触Rust仅2周,使用搭载STM32L0的自定义开发板,基于Embassy开发

目标逻辑(伪代码)

repeat{
    set timer interrupt1 at 5 miliseconds;
    set timer interrupt2 at 10 miliseconds;
    wait 100 miliseconds;
}
interrupt1: set pin high
interrupt2: set pin low

注:此逻辑可通过其他方式实现,核心目的是理解中断工作原理,为后续项目做准备

当前尝试的代码

#![no_std]
#![no_main]

use cortex_m::interrupt as cortex_interrupt;
use embassy_executor::Spawner;
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_time::Timer;
use {defmt_rtt as _, panic_probe as _};
use embassy_stm32::interrupt;

#[interrupt]
unsafe fn TIM2(){
    let pin = embassy_stm32::peripherals::PB0::steal();
    let mut pin2 = Output::new(pin, Level::High, Speed::Low);
    pin2.set_high();
}
#[interrupt]
unsafe fn TIM21(){
    let pin = embassy_stm32::peripherals::PB0::steal();
    let mut pin2 = Output::new(pin, Level::High, Speed::Low);
    pin2.set_low();
}

#[embassy_executor::main]
async fn main(_spawner: Spawner) {
    let p: embassy_stm32::Peripherals = embassy_stm32::init(Default::default());
    unsafe {cortex_interrupt::enable();}
    loop{
        Timer::after_millis(1000).await;
    
    }
}

自行查找时遇到的问题

  • 查阅《Rust嵌入式编程书籍》中断章节,未找到如何调度/触发中断的说明
  • 参考Embassy相关GitHub问题时,代码中的InterruptExecutor出现“未解析的导入”错误
  • 查看Embassy官方文档,未找到对应解决方案
  • StackOverflow上的类似问题无有效回复
  • AI生成的代码均无法编译

解决方案与信息查找指南

一、定时器中断实现修正

核心问题分析

  1. 当前代码仅定义了中断处理函数,但未对定时器进行初始化(配置定时周期、开启中断、启动定时器)
  2. 中断函数中重复steal()引脚并重新初始化,会导致资源冲突,引脚应在main中初始化后通过共享方式访问

修正后的代码

#![no_std]
#![no_main]

use cortex_m::interrupt::{self, Mutex};
use embassy_executor::Spawner;
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_stm32::interrupt::InterruptExt;
use embassy_stm32::timer::{simple_timer::SimpleTimer, Timer as Stm32Timer};
use embassy_time::Timer;
use {defmt_rtt as _, panic_probe as _};
use embassy_stm32::peripherals::{TIM2, TIM21, PB0};

// 用Mutex共享引脚资源,确保中断安全
static PIN: Mutex<Option<Output<'static, PB0>>> = Mutex::new(None);

#[interrupt]
fn TIM2() {
    // 获取定时器实例并清除中断标志
    let tim2 = unsafe { TIM2::steal() };
    Stm32Timer::<TIM2>::clear_interrupt(&tim2);
    
    // 安全访问引脚并设置高电平
    interrupt::free(|cs| {
        if let Some(pin) = PIN.borrow(cs).as_mut() {
            pin.set_high();
        }
    });
}

#[interrupt]
fn TIM21() {
    // 获取定时器实例并清除中断标志
    let tim21 = unsafe { TIM21::steal() };
    Stm32Timer::<TIM21>::clear_interrupt(&tim21);
    
    // 安全访问引脚并设置低电平
    interrupt::free(|cs| {
        if let Some(pin) = PIN.borrow(cs).as_mut() {
            pin.set_low();
        }
    });
}

#[embassy_executor::main]
async fn main(_spawner: Spawner) {
    let p = embassy_stm32::init(Default::default());
    
    // 初始化引脚并存入Mutex
    let pin = Output::new(p.PB0, Level::Low, Speed::Low);
    interrupt::free(|cs| {
        *PIN.borrow(cs) = Some(pin);
    });

    // 初始化TIM2:5ms定时
    let mut tim2 = SimpleTimer::new(p.TIM2);
    tim2.set_period(5_000); // 单位:微秒
    tim2.enable_interrupt();
    tim2.start();
    // 启用TIM2中断
    unsafe {
        embassy_stm32::interrupt::TIM2.unmask();
    }

    // 初始化TIM21:10ms定时
    let mut tim21 = SimpleTimer::new(p.TIM21);
    tim21.set_period(10_000);
    tim21.enable_interrupt();
    tim21.start();
    // 启用TIM21中断
    unsafe {
        embassy_stm32::interrupt::TIM21.unmask();
    }

    loop {
        Timer::after_millis(100).await;
        // 每次循环重启定时器(如果需要重复触发)
        tim2.restart();
        tim21.restart();
    }
}

代码说明

  • 使用Mutex实现中断安全的资源共享,避免引脚重复初始化
  • 通过SimpleTimer简化定时器配置,设置周期、开启中断并启动
  • 中断处理函数中必须清除中断标志,否则会持续触发中断
  • 循环中重启定时器以实现每100ms重新触发5ms和10ms中断的逻辑

二、嵌入式Rust+Embassy信息查找有效途径

  1. Embassy官方示例库:优先查看针对STM32的定时器、中断相关示例,示例代码是最直接的参考,涵盖了框架的标准用法
  2. Embassy API文档:重点关注embassy-stm32下的timer、interrupt模块,以及对应芯片的外设文档,文档中会标注每个功能的初始化步骤和中断启用方法
  3. Rust Embedded社区Discord:社区内有大量经验丰富的开发者,针对Embassy的问题提问通常能得到快速回复
  4. STM32官方参考手册:定时器的核心工作原理(如计数模式、中断触发条件)需要参考芯片的官方RM手册,这是底层逻辑的源头
  5. Embassy GitHub仓库issues和PR:搜索已解决的同类问题,注意查看issue的时间,避免参考过时的API用法(Embassy迭代较快,旧代码可能不兼容新版本)
  6. 《Rust Embedded Book》进阶章节:书中的中断章节基础内容可结合框架文档拓展,重点理解中断安全、资源共享等核心概念

内容的提问来源于stack exchange,提问作者Wouter Van Bastelaere

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 08:20:55