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

AVR汇编下ATMega328p INT0外部中断无法触发问题求助

AVR汇编INT0中断无法触发的问题排查与修复

你的代码存在以下几处问题,按影响优先级排序:

1. 核心错误:EIMSK寄存器写入指令错误

ATMega328p的EIMSK(外部中断掩码寄存器)属于低地址IO寄存器,IO地址为0x1D,仅支持使用out指令直接写入IO空间。
你使用sts EIMSK, r16写入时,默认头文件中EIMSK定义为IO地址0x1D,sts指令是向数据空间写入,数据空间0x1D对应通用寄存器r29的地址,根本没有写入到中断控制寄存器,导致INT0中断从未开启。
修复方案:将sts EIMSK, r16改为out EIMSK, r16。

2. PD2引脚输入模式配置不合理

你通过cbi PORTD, 0x02将PD2设置为浮空输入,没有开启内部上拉,引脚电平处于不确定状态,即使外接触发信号也可能无法正常识别电平变化。
修复方案:如果你的触发逻辑是外部拉低PD2触发中断,将cbi PORTD, 0x02改为sbi PORTD, 0x02开启内部上拉电阻,引脚默认电平为高,外部拉低即可触发。

3. EICRA配置存在冗余(可选优化)

你写入EICRA的值为0x05(二进制00000101),除了配置INT0为电平变化触发外,还意外开启了INT1的电平变化触发,属于多余配置。
如果你的需求是INT0电平变化触发,修改为ldi r16, 0x01即可;如果需要其他触发模式,调整对应位即可:

  • 下降沿触发:ldi r16, 0x02(ISC01=1,ISC00=0)
  • 上升沿触发:ldi r16, 0x03(ISC01=1,ISC00=1)

4. 中断服务程序写法存在隐患

你使用全局寄存器r16保存LED状态,虽然当前主循环不会修改r16,但后续代码扩展后很容易出现冲突。更可靠的LED翻转方式是直接写PINB寄存器:向PIN寄存器的对应位写1即可自动翻转IO电平,不需要额外寄存器保存状态。

修正后的完整代码

.list               
.org 0x0000
    rjmp main
.org 0x0002 
    rjmp INT0_ISR       
.org INT_VECTORS_SIZE
.def dreg = r18
main:           
    cli                
    ldi r17, LOW(RAMEND)
    out SPL, r17
    ldi r17, HIGH(RAMEND)
    out SPH, r17            ; 设置栈指针
    sbi DDRB, 0x05          ; 设置PB5为输出(对应D13)
    sbi PORTB, 0x05         ; 初始点亮LED
    cbi DDRD, 0x02          ; 设置PD2为输入
    sbi PORTD, 0x02         ; 开启PD2内部上拉
    ldi r16, 0x01           ; 使能INT0中断
    out EIMSK, r16          ; 改用out指令写EIMSK
    ldi r16, 0x02           ; 配置INT0为下降沿触发
    sts EICRA, r16
    sei    
loop:          
    rjmp loop
INT0_ISR:    
    push r17
    in r17, SREG            ; 保存状态寄存器
    sbi PINB, 5             ; 直接翻转PB5电平
    out SREG, r17           ; 恢复状态寄存器
    pop r17            
    reti                    ; 退出中断

内容的提问来源于stack exchange,提问作者Chandler Klüser

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 08:24:10