【发布时间】:2016-09-07 04:48:49
【问题描述】:
我想在 AVR 程序集中创建一个程序,该程序将轮询瞬时按钮开关的状态,并在按下开关时切换 LED 的状态。我正在使用带有 ATMega328P 芯片的 Arduino Duemilanove。我在数字引脚 0 和地之间连接了一个按钮开关,在数字引脚 8 和 +5V 之间连接了一个带有 330 欧姆电阻的 LED。到目前为止,这是我的代码:
;==============
; Declarations:
.def temp = r16
.org 0x0000
rjmp Reset
;==============
Reset:
ser temp
out DDRB, temp ; set all pins on Port B to OUTPUT mode
ldi temp, 0b11111110 ; set pin 0 on Port D to INPUT mode
out DDRD, temp
clr temp
out PORTB, temp ; clear temp and set all pins on Port B to LOW state
ldi temp, 0b00000001 ; set pin 0 on Port D to HIGH state
out PORTD, temp
;==============
; Main Program:
switch:
in temp, PIND ; get state of pins on Port D
cpi temp, 0 ; compare result to 0 (pushbutton is pressed)
brne PC+3 ; if != 0, go check again
ldi temp, (1<<PB0) ; otherwise, write logic 1 to pin 0 of Port B
out PINB, temp ; which toggles the state of the pin
rjmp switch
不幸的是,这一切只是点亮 LED 并让 LED 保持亮起,无论按多少次按钮。我将这段代码基于找到的一个程序here,该程序只要按下按钮就会打开LED。我只是想扩展它以将 LED 保持在当前状态,直到再次按下按钮。有什么建议吗?
【问题讨论】:
-
您应该只比较
PIND0和0,方法是使用掩码而不是整个PIND。特别是如果您的端口处于浮动状态(二极管上的照明可能会改变浮动引脚的电平并使cpi temp, 0始终错误)。此外,您可以使用SBI指令更改PINB中的单个位。不确定这是否可行,但目前我没有看到其他问题。 -
按钮弹跳。这在示例代码中无关紧要,但在您的情况下,即使在@Julien 的提示之后,您也会收到随机结果。
-
我已经尝试过如何使用
sbi将逻辑 1 写入 PB0,但我似乎无法让它工作。使用 `sbi PORTB0, 1` 不会给出预期的结果。我明白你关于按钮弹跳的观点。也许主循环中某处的延迟子程序会使开关反跳? -
@JoshBenson 我对数据表的理解是
sbi PORTB, 0(不需要 1,因为 Sbi 用于设置位(cbi 清除位))。是的,按下检测后会有一些延迟会去抖动
标签: assembly arduino avr atmega