Electronic – How to use a button to wake up an atmega32

atmegabuttonmicrocontrollersleep

Sorry for any noobiness, I'm more of a software engineer.

How do I use button interrupts in general?

As in, if I put my microcontroller to sleep, I'd like a button to wake it up.

How should I go about doing this?

Edit

Adding this to main, thanks to @jippie

DDRD &= ~(1<<PIND2)
PORTD |= 1<<PIND2
GICR  |=   ( 1 << INT0 );   // Enable INT0
MCUCR = (0<<ISC00)|(1<<ISC01);

sei();

And this outside of main

ISR(INT0_vect) {
  sleep_disable(); // If ISR got called while it was sleeping, this would work
  lcd.string("works");
};

ISR does work, but only if the device is not sleeping.

FIXED

Changing from INT0 to INT2 ( and moving from PIND2 to PINB2 ), it works…

According to documentation, INT0 and INT1 use level interrupts but PINB uses edge… so.. that's maybe why?

My voltage meter drops to .2 while in sleep mode, then wakes up from ISR.

Best Answer

\$\overline{\mathsf{RESET}}\$

A push button from \$\overline{\mathsf{RESET}}\$ to ground is the easiest way, but it forgets current state entirely.

Interrupts

For interrupts to work you need a pin that attributed as INTn and for ATmega32 you are limited to PB2, PD2 or PD3. Not all sleep modes support waking up by external interrupt and different sleep modes support edge or level triggered interrupts.

For thes pins you have to:

  • Enable the interrupt in the General Interrupt Control Register GICR;
  • Review the Interrupt Sense Control bits in MCUCR and MCUCSR.

You don't need to add an complete ISR (interrupt service routine) if all you want to do is wake up and continue where you left off, but you shouldn't rely on the default vector. It depends on the compiler what actually happens on a bad interrupt. Refer here for the name of the interrupt vector to use.

ISR() { INT0_vect , EMPTY_INTERRUPT };

For details check the chapter titled 'External Interrupts' in the ATmega32 datasheet.

For a button to ground on PD2 (INT0) code might look a bit like this (untested):

DDRD  &= ~ ( 1 << PD2 );    // Configure PD2 as input
PORTB |=   ( 1 << PD2 );    // Enable pull up resistor
// MCUCR default triggers on LOW level. Changing to edge trigger requires different sleep mode to wake up.
GICR  |=   ( 1 << INT0 );   // Enable INT0