# How do I read digital input on ATmega16?

What do I have to do to read a digital input (pushbutton) on ATmega16? Do I have to enable pullup-resistors or can I use a 10 kohm one? What would some simple code be be? Just a simple 'Turn the LED on when it's pressed thing'.

Is there a beginner's tutorial? I have tried googling and AVR Freaks, but everything just evolves into a fight there and I don't get my answer. I really haven't found any tutorials about this stuff. Tons of specific things but nothing simple about my AVR microcontroller...

-
This would be answered in pretty much any beginner's tutorial, and I fear a complete answer here would undermine your understanding more than help. What prior effort have you done to learn? – Yann Vernier Oct 17 '10 at 12:51
Not sure if you saw my post or are you able to see it (sorry still kinda confused about this site...) But i know the code, lets say my question is: do i just connect a pin to GND and its low? – curious Oct 17 '10 at 13:20
Why not edit you post to more accurately reflect this and include the post below in the original post too. – Amos Oct 17 '10 at 14:13
Try the From-Scratch AVR Tutorial on this AVR Freaks page. You'll find lots more stuff there. – Leon Heller Oct 17 '10 at 15:40

Brazilian greetings!

First of all thanks Joby for your example. Secondly, his example has just a minor error. The number 0x20 is not correct. It should be 0x04. Also, just as a suggestion, I would not use hexadecimal numbers like 0xFB, 0x20, or 0x04 in the code. I would suggest using the PIN port definitions found in the io.h and other ones referenced by header file. I have rewritten Joby's example below, with some comments for the beginners.

# include <avr/io.h>

int main (void)
{
// set all pins on PORTB for output
DDRB = 0xFF;

// set port pin PORTD2 as input and leave the others pins
// in their originally state (inputs or outputs, it doesn't matter)
DDRD &= ~(1 << PD2);        // see comment #1

while (1)
{
if (PIND & (1<<PD2))    // see comment #2
PORTB |= (1<<PB2);  // see comment #3
else
PORTB &= ~(1<<PB2); // see comment #4
}
return 0;
}


/*

comment #1: (1 << PD2) generates the binary 00000100. The operation "~" flips all the digits, i.e., the binary now is 11111011. Finally the &= applies the logic "AND" between DDRD and 11111011 and the result is placed again in DDRD memory. Note: What the operator "AND" does is for each bit in the DDRD memory, it compares with the binary number above. If the bit in DDRD is 0 and the bit in the binary at the same bite position is 1, then the resulting bit is 0, if the DDRD is 1 and the bit in the binary is 1, the resulting bit is 1, and if the bit in the DDRD is 1 or 0 and the bit in the binary is 0 then the resulting bit is always 0. In summary, the command DDRD &= ~(1 << PD2) changes only the bit PD2 to zero and leave the other ones (zeros or ones) untouched. It seems a little bit complicated, but after you get used to it, it is the best way of changing a bit in a bite without changing the other bits.

comment #2: (1 << PD2) generates the binary 00000100. Using the same logic "AND" described in comment #1, the command "PIND & 0000100" checks only if the PIND2 (our input pin where the push button is connected to) is set to high or not. All the other pins will be FALSE since the binary bits are set to 0, and since the binary bit #2 is set to 1, the IF statement will be TRUE only if the PD2 input is set to high or FALSE if the PD2 input is set to low.

comment #3: Following the logic explained in comment #1, this command sets output pin PINB2 in port PORTB to high voltage. If your LED is correct connected to this pin port with a resistor of ~300 ohms, and that resistor is connected to the ground, the LED should turn on.

comment #4: The LED should turn off for the same reasons explained in the previous comments.

Final considerations:

b) A disclaim note: The ideas described here are to be used as educational only and they should NOT be used in any real system before consulting an expert in electronics.

*/

-
I don't encourage you to give your email because corresponding by email makes the communication private. So nobody else can benefit. But if you really wants to provide your email for private communications, the best place to do that is in your profile. – Daniel Grillo Mar 7 '11 at 1:18

https://www.mainframe.cx/~ckuethe/avr-c-tutorial/

https://www.mainframe.cx/~ckuethe/avr-c-tutorial/#digital-in

#include <avr/io.h>

/*
* Assumptions:
*  - LED connected to PORTB.2
*  - Switch connected to PORTD.2
*/

int main (void)
{
/* set PORTB for output*/
DDRB = 0xFF;
/* set PORTD for input*/
DDRD &= 0xFB;
PORTD |= 0x04;

while (1) {
if (PIND & 0x04)
PORTB &= ~0x20;
else
PORTB |= 0x20;
}
return 0;
}

-
 Thankx to @joby Taffey for the supplied link. I was searching for EEPROM functions and I got a lot of help from : mainframe.cx/~ckuethe/avr-c-tutorial/lesson11.c Thank you very much. – Bishal Paudel Oct 18 '11 at 10:33

Well this is for the AT90Usb1287, a ATMega, but the basic button stuff should be more or less the same. Just change the IO names.

-

Something else to consider when dealing with a digital input from a mechanical switch is the contacts bouncing -- changing what should be a single button push into what looks like multiple pushes.

For something like turning on an LED when the button is held down, you probably don't have to worry about debouncing. For something a little more complicated (like toggling the LED on the button press), debouncing is a must.

Jack Ganssle has a good Guide to Debouncing

-