Reputation: 236
I want to create a program in AVR assembly that will poll the state of a momentary pushbutton switch and toggle the state of an LED whenever the switch is pressed. I am using an Arduino Duemilanove with an ATMega328P chip. I have a pushbutton switch connected between digital pin 0 and ground, and an LED with 330 ohm resistor connected between digital pin 8 and +5V. Here is my code so far:
;==============
; 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
Unfortunately all this does is light the LED and keep it on no matter how many times the button is pushed. I am basing this code off of a program found here that turns the LED on as long as the button is pushed. I simply want to extend that to hold the LED in its current state until the button is pushed again. Any suggestions?
Upvotes: 0
Views: 7776
Reputation: 379
you can toggle it by using NOT operator
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
Upvotes: 1
Reputation: 123
This code changes the value so quickly, that you won't be able to notice any change. Everytime you press the button, it will keep toggling the value for whole time it's pressed down. You should add some delay or simply ignore the on state for some time. Also, you should pick up from PIND only what you want, by masking it (easiest way is to use andi).
.def del = r15
clr del
switch:
in temp, PIND ; get state of pins on Port D
andi temp, (1<<PD0) ; you should mask to get only what you want
cpi temp, 0 ; compare result to 0 (pushbutton is pressed)
brne switch ; if != 0, go check again
cpi del, 0 ; compare del to 0
brne dec_jmp ; if != 0, ignore this run
ldi temp, (1<<PB0) ; otherwise, write logic 1 to pin 0 of Port B
out PINB, temp ; which toggles the state of the pin
ldi del, 250 ; next one will be ignored for 250 runs
dec_jmp:
dec del ; decrement del
rjmp switch
Upvotes: 1
Reputation: 1243
Your only ever writing a HIGH to PB0. Each time the key is pressed you need to invert the pins state for example
in temp, PORTB
com temp
out PINB, temp
As you've previously set temp to 1 then 1's compliment would change it to 11111110 thus writing a zero to PINB0 and the next time it would be 00000001 turning the led back on.
This over simplistic solution has an unpredictable side affect in that it doesn't take bounce into consideration, therefor you're not really guaranteed the LED will be on or off when you release the button as expected. That is a question that digresses from the scope of this one and should be asked separately. Just wanted to give you a heads up here.
Upvotes: -1