Reading AVR button status using WinAVR

If you want to bring some interactivity to your embedded projects, one option is to add buttons. This allows you to control program flow, set parameters, and much more.

Few words about AVR ports. AVR Port pins can be configured as input or output. See table for all general pin configurations:

  • DDRx register is the so-called direction register;
  • PORTx – is port output register;
  • PINx – is pin input register;

So there can be three options for input and two for output. If you are doing some simple routines with AVR microcontrollers, you maybe are familiar with configuring output from port. Just write ‘1’ to DDRx register and then send data to the PORTx register:

For instance:

DDRD=0x0F; //sets lower nibble as output;

PORTD=0x05 //output ‘1’ to PORTD pins 0 and 2;

If you want to read input signals, there are normally a couple of ways to do this. For input DDRx register should always be set as input ‘0’ pin values. PORTx register can be set in two ways:

If PORTx is set to ‘1’, the internal pull-up resistor is enabled depending on the PUD bit in the SFIOR register. If the PORTx pin is set to ‘0’, then internal pull-up is disabled despite PUD settings.

Normally PUD bit is set to ‘0’ what means that this enables internal pull-ups.

If you do not touch SFIOR register then you have to write:

DDRD=0x0F; //sets higher nibble as input;

PORTD=0x50 //sets port pins 4 and 6 as input with pull-ups and pins 5 and 7 without pull-ups (tristate);

Enough theories. Couple examples will make it more clear.

  • The simplest way to connect the button to the AVR microcontroller is to connect it directly to the ground:

In this case internal pull-up is enabled by writing ‘1’ to PORTD.

Internal pull-up is disabled by writing ‘0’ to PORTD or Setting PUD bit to ‘1’.

  • Similar situation may be when using Pull-down resistor:

Let’s take the simplest way (internal pull-up enabled and button connected to ground) and write a simple routine using WinAVR:

#include "avr\io.h"
#include "avr\iom8.h"
int main(void) {
DDRD&=~_BV(0);//set PORTD pin0 to zero as input
PORTD|=_BV(0);//Enable pull up
PORTD|=_BV(1);//led OFF
DDRD|=_BV(1);//set PORTD pin1 to one as output
while(1) {
if (bit_is_clear(PIND, 0))//if button is pressed
PORTD&=~_BV(1);//led ON
loop_until_bit_is_set(PIND, 0);//LED ON while Button is pressd
PORTD|=_BV(1);//led OFF

Sample project fiels ready to go with VMLAB

One Comment:

  1. thanks… I was freaking out with INT2… because a silly wiring…

Leave a Reply