# Atmega328p: why button input is read as 0 when pressed?

I'd like to turn on the board's LED (PB5) when I press its button (PB7).

DDRB = 0xFF; // set all B-ports as output
DDRB &= ~(1<<7); // change PB7 to input
while (1)
{
if (PINB & (1<<7))
PORTB |= (1<<5); // when button is pressed, turn on the LED
else
PORTB &= ~(1<<5); // when button is not pressed, turn off the LED
}


However, PINB & (1<<7) returns 1 when I except 0, and 0 when I press the button. I could add a not operator and it'd be fine, but I'd like to know what I missunderstand. Why is the 8th bit of PINB read as 0 when I press the button?

• Post a schematic that shows how the button is connected up. Some circuits have the button pull down the signal pin of the MCU when the button is pressed. – Michael Karas May 21 '16 at 17:12
• Simple: !(PINB & (1<<7)). Now you get a 1 when the button is pressed and a 0 when released. – Tom Carpenter May 21 '16 at 17:24
• Almost every single button I have ever put in a schematic was "active low" meaning that one terminal was connected to ground, and the other one was connected to both a pullup resistor and a GPIO. Of course it is possible to do it the other way, too. But it appears that in your case, it is an active low signal (low = button pressed). – mkeith May 21 '16 at 19:25
• PINB & (1<<7) might evaluate to true but it cannot evaluate to 1 without additional operations. – Chris Stratton May 21 '16 at 20:51
• @ChrisStratton That's true, by 1 I meant non-zero which equals to true in an if, but right now this isn't important. – klenium May 21 '16 at 20:54

What PINB & (1<<7) will return depend on how the button is wired. It will return true (not 0) value if the voltage on the pin is in the range of the high logic level and false (0) if it is in the range of the low logic level.

In the first case, the GPIO pin is pulled up to VCC (logic high) by default, so if the button is not pressed PINB & (1<<7) will return true. If you press the button, the voltage at the pin will be GND (logic low), so your statement will return false (0).

In the second case the configuration is reversed. The pin is pulled down to GND by default and when the button is pressed the voltage will be VCC. So the input will be true on button presses.

simulate this circuit – Schematic created using CircuitLab

On your board, you probably have the first case.

• I found this in the board's user guide: i.stack.imgur.com/Gji5D.png I'm a bit new in electronics, and for me (as programmer) default was=0, in use=1. – klenium May 21 '16 at 20:50
• You are preserving an error made by the poster. PINB & (1<<7) might evaluate to true but it cannot evaluate to 1 – Chris Stratton May 21 '16 at 20:52
• @Chris Stratton Indeed, thank you for pointing out, corrected this issue. – Bence Kaulics May 21 '16 at 21:18