尝试通过以下行在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工作室的问题。
答案 0 :(得分:1)
还要检查以下几点:
EIMSK
位于OUT
支持的地址范围内。如果通过数据存储/加载指令引用它,则必须向其地址除此之外,我认为让按钮触发中断不是一个好主意,因为按钮反弹。因此,每按一次按钮就可以获得几十个中断。
你应该阅读有关去抖动技术的内容,并考虑使用软件去抖动定时器中断驱动的按钮状态读数。 如果您了解德语,您可以阅读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