在AVR上启用外部中断

时间:2014-08-31 10:33:45

标签: assembly avr atmelstudio

尝试通过以下行在ATmega328P上启用外部中断:

LDI R16, (1 << ISC00) | (1 << ISC01)
LDI R17, (1 << INT0)

STS EICRA, R16
STS EIMSK, R17

SEI

在我的重置子程序中。

想法是让INT0在上升沿触发外部中断(即从按下按钮)。已在JMP处将中断向量表放入适当的0x0002指令。

在使用模拟器在Atmel Studio 6中进行调试期间,当我切换INT0引脚时,不仅没有中断运行,同时手动跳过指令我发现EIMSK寄存器没有被更新并且指令尽管在执行该指令之前将R17设置为0x01,STS EIMSK, R17似乎完全没有做任何事情。

在AVR大会上相当一个菜鸟,这是我的代码或atmel工作室的问题。

1 个答案:

答案 0 :(得分:1)

还要检查以下几点:

  • 请重读数据表部分&#34; 8.5 I / O Memory&#34;。 EIMSK位于OUT支持的地址范围内。如果通过数据存储/加载指令引用它,则必须向其地址
  • 添加一些常量(0x20)
  • 是否设置为intput?
  • 是否存在一些上拉/下拉?
  • 你定义了一些ISR吗?

除此之外,我认为让按钮触发中断不是一个好主意,因为按钮反弹。因此,每按一次按钮就可以获得几十个中断。

你应该阅读有关去抖动技术的内容,并考虑使用软件去抖动定时器中断驱动的按钮状态读数。 如果您了解德语,您可以阅读http://www.mikrocontroller.net/articles/Entprellung 这是一篇非常好的文章,也是一个有效且好的实现,可以对多个键进行去抖动。

编辑:

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=54896&start=0这个问题被问到:

  

某些寄存器都是IO和存储器映射,所以既不是“OUT”,也不是“OUT”。和   &#39; STS&#39;生成编译器错误但只有一个有效。怎么会这样   很容易确定?

给出了两个答案。一个非常务实的方法:

  

默认情况下使用IN / OUT,并且只有编译器错误的LDS / STS是正确的

另一个建议使用一些区分两种情况的asembler宏(没有测试它们):

; usage: InReg reg, addr
.macro InReg
    .if @1 < 0x40
        in @0, @1
    .elif ((@1 >= 0x60) && (@1 < SRAM_START))
        lds @0,@1
    .else
       .error "InReg: Invalid I/O register address"
    .endif
.endmacro

; usage: OutReg addr, reg
.macro OutReg
    .if @0 < 0x40
        out @0, @1
    .elif ((@0 >= 0x60) && (@0 < SRAM_START))
        sts @0,@1
    .else
       .error "OutReg: Invalid I/O register address"
    .endif
.endmacro