2

尝试通过以下行在 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寄存器没有被更新,并且STS EIMSK, R17尽管 R17 指令似乎完全没有做任何事情在执行该指令之前被设置为 0x01。

在 AVR 组装方面相当菜鸟,这是我的代码问题还是 atmel 工作室的问题。

4

1 回答 1

1

还要检查以下几点:

  • 请重新阅读数据手册“8.5 I/O 存储器”部分。 EIMSK位于受支持的地址范围内OUT。如果您通过数据存储/加载指令引用它,则必须在其地址中添加一些常量(0x20)
  • 引脚设置为输入吗?
  • 是否存在一些上拉/下拉?
  • 你定义了一些 ISR 吗?

除此之外,我认为让按钮触发中断不是一个好主意,因为按钮会弹跳。所以每次按下按钮都会有几十个中断。

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

编辑:

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

有些寄存器是 IO 和内存映射的,所以“OUT”和“STS”都不会产生编译器错误,但只有一个有效。这怎么能很容易地确定呢?

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

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

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

; 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 
于 2014-09-01T11:06:54.993 回答