I want to make a simple circuit that when you press a pushbutton, an LED lights up stays lit until the button is pressed again. I haven't delved into interrupts yet on AVR, and was wondering whether it is possible to do in a while
loop.
This is my code:
#include <avr/io.h>
#define INPUT (1 << PINB3)
#define OUTPUT (1 << PINB0)
int main(void)
{
DDRB = 0x00; //everything input
PORTB = 0x00; //no pud
DDRB |= 0x1; //PB0 is an output
PORTB = 0x00; //PB0 is low and PUD is off
uint8_t prev = PINB;
while(1)
{
if ((prev & INPUT) < (PINB & INPUT)) { //rise edge
if ((PORTB & OUTPUT) == 0x0) { //if output was low
PORTB |= OUTPUT; //make output high
} else {
PORTB &= ~OUTPUT; //make output low
}
}
prev = PINB;
}
}
The switch only partially works, I'm guessing because of the nature of the while loop and it storing the previous input really fast.
I believe the problem lies in my method of detecting a rising edge of the push-button. What would be a better method?
Best Answer
Your problem might be bouncing. When you press or release a button, it bounces. (see picture). This is due to mechanical bounces of the electrical contacts inside the button itself.
You have to take this into account and reject the bounces. This can be done in software. A lot of method exists, using timer, interrupts, wait loops etc. Google the web and choose the implementation that fits your system best.
You can also have a look here: debouncing-buttons