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

如何在ISR中清除或阻止挂起中断?基于ATSAMD21的技术问询

解决ATSAMD21 ISR执行期间额外中断触发的问题

针对你遇到的ATSAMD21(Cortex-M0+)外部中断ISR重复触发问题——真实中断触发一次却导致两次ISR执行,核心原因是ISR执行期间数据引脚的额外下降沿触发了EIC(外部中断控制器)的中断请求,且之前的中断禁用/清除操作顺序错误,没有从源头阻断中断请求。

有效解决方案代码

假设触发引脚对应EXTINT2,正确的ISR实现需从**中断源头(EIC)**入手,按「禁用EIC引脚中断 → 清除EIC中断标志 → 清除NVIC挂起 → 执行业务逻辑 → 恢复EIC引脚中断」的顺序操作:

#include <samd21.h>

void interrupt_cb(void)
{
    // 1. 先禁用对应引脚的EIC中断(阻断中断源头)
    EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT2;
    __DSB(); // 确保寄存器写操作完成,防止编译器重排
    
    // 2. 清除EIC的中断标志位(ATSAMD21需写1清除)
    EIC->INTFLAG.reg = EIC_INTFLAG_EXTINT2;
    __DSB();
    
    // 3. 清除NVIC中的挂起中断,避免残留请求
    NVIC_ClearPendingIRQ(EIC_IRQn);
    __ISB(); // 确保NVIC状态同步更新
    
    // ------------------------------
    // 4. 执行你的24位数据读取逻辑
    // < 这里放你的位bang设备读取代码 >
    // ------------------------------
    
    // 5. 重新启用对应引脚的EIC中断,准备响应下一次真实中断
    EIC->INTENSET.reg = EIC_INTENSET_EXTINT2;
    __DSB();
}

为什么之前的操作无效?

你之前尝试的方法存在几个关键问题:

  1. 操作顺序错误:先禁用NVIC或全局中断,再处理EIC——NVIC只是中断分发器,EIC作为中断源仍会产生请求,导致NVIC挂起位被反复置位。必须先从EIC层面禁用引脚中断,阻断源头。
  2. 未清除EIC中断标志:ATSAMD21的EIC中断标志位(INTFLAG)需要写1清除,若只清NVIC挂起位,EIC的未处理标志会持续向NVIC发送请求,导致挂起位再次被置位。
  3. 全局中断操作无效:Cortex-M0+进入ISR时会自动设置PRIMASK屏蔽全局中断,退出时自动恢复,ISR内调用__disable_irq()不会改变最终中断状态,反而可能干扰正常流程。

额外注意事项

  • 硬件滤波:如果数据引脚的额外下降沿由噪声导致,建议在引脚上添加100nF左右的滤波电容,从根源减少误触发。
  • 寄存器volatile修饰:确保EIC相关寄存器的访问被编译器视为易变的,避免优化导致操作丢失(可直接使用SAM库提供的宏)。
  • 调试验证:可在ISR开头和结尾添加GPIO翻转操作,配合示波器观察ISR执行次数,验证解决方案是否生效。

内容的提问来源于stack exchange,提问作者aulven

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 23:20:42