我想在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并保持亮起。我将此代码基于找到here的程序,只要按下按钮就会打开上的LED。我只是想扩展它以使LED保持当前状态,直到再次按下按钮。有什么建议吗?
答案 0 :(得分:1)
此代码更快地更改了值,使您无法注意到任何更改。 每次按下按钮,它都会在整个按下时间内切换值。你应该添加一些延迟或者只是忽略on状态一段时间。此外,您应该通过屏蔽(最简单的方法是使用andi)从PIND中获取您想要的内容。
E/App: error message: null
答案 1 :(得分:0)
您可以使用NOT运算符
切换它ldi temp2,0
switch:
in temp,PIND
andi temp,1 ; remove all results except bit.0
cpi temp,0 ; if pressed (i assume the button is active low)
brne switch ; loop again if not pressed
mov temp2,!temp2 ; not operator
out PORTB,temp2 ; toggle PORTB output
rjmp switch ; back to main loop
答案 2 :(得分:-1)
你唯一一次向PB0写高电平。每按一次键,您需要反转引脚状态,例如
in temp, PORTB
com temp
out PINB, temp
由于您之前已将temp设置为1,因此1的赞美会将其更改为11111110,从而将零写入PINB0,下次将00000001重新打开LED。
这种过于简单的解决方案具有不可预测的副作用,因为它没有考虑反弹,因此当你按预期释放按钮时,你并没有真正保证LED会打开或关闭。这个问题偏离了这个问题的范围,应该单独提出。只是想在这里给你一个提示。