¿Cómo uso un botón para activar un atmega32?

Perdón por cualquier noobiness, soy más un ingeniero de software.

¿Cómo uso las interrupciones de botón en general?

Es decir, si pongo mi microcontrolador a dormir, me gustaría un botón para despertarlo.

¿Cómo debo hacer esto?

Editar

Agregando esto a main, gracias a @jippie

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

sei();

Y esto fuera de main

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

ISR funciona, pero solo si el dispositivo no está durmiendo.

FIJADO

Cambiando de INT0 a INT2 (y pasando de PIND2 a PINB2), funciona...

De acuerdo con la documentación, INT0 e INT1 usan interrupciones de nivel, pero PINB usa edge... así que... ¿quizás por eso?

Mi medidor de voltaje cae a .2 mientras está en modo de suspensión, luego se despierta de ISR.

¡Bienvenido al sitio Funkodebat! Puede que te guste este tutorial: avratmega32.blogspot.com/2011/07/sleep-modes-of-atmega32.html
Creo que este tutorial sobre interrupciones ayudará: newbiehack.com/IntroductiontoInterrupts.aspx

Respuestas (2)

R mi S mi T ¯

Un pulsador de R mi S mi T ¯ a tierra es la forma más fácil, pero olvida el estado actual por completo.

Interrupciones

Para que las interrupciones funcionen, necesita un pin que se atribuya como INTny para ATmega32 está limitado a PB2, PD2o PD3. No todos los modos de suspensión admiten la activación por interrupción externa y los diferentes modos de suspensión admiten interrupciones activadas por borde o nivel.

Para estos pines tienes que:

  • Habilitar la interrupción en el Registro General de Control de Interrupciones GICR;
  • Revise los bits de Control de Sentido de Interrupción en MCUCRy MCUCSR.

No necesita agregar una ISR (rutina de servicio de interrupción) completa si todo lo que quiere hacer es despertar y continuar donde lo dejó, pero no debe confiar en el vector predeterminado. Depende del compilador lo que realmente suceda en una mala interrupción. Consulte aquí el nombre del vector de interrupción a utilizar.

ISR() { INT0_vect , EMPTY_INTERRUPT };

Para obtener más información, consulte el capítulo titulado 'Interrupciones externas' en la hoja de datos de ATmega32 .

Para que un botón se conecte a tierra en PD2 ( INT0), el código podría parecerse un poco a esto (no probado):

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
Entonces... si un botón ya está conectado a PIND5... ¿cómo sería un código de ejemplo para hacer esto?
Entonces, para PD2, ¿es posible despertarse del modo power_down?
@Funkodebat no puede usar PD5como entrada de interrupción. Actualicé mi respuesta. Se agregó un código de muestra (no probado).

La respuesta de Jippie tiene los detalles técnicos, pero es posible que no estés comprendiendo los modos de suspensión de los AVR. Los microcontroladores operan en un ámbito diferente al que estamos acostumbrados a que las computadoras de escritorio funcionen y, de hecho, golpean algunas de las mismas palabras para significar cosas que los desarrolladores de software no esperan.

Lo siguiente es lo que he recopilado, como un tipo de software. ¡Agradezco de todo corazón las modificaciones a mi publicación para corregir las cosas en las que me he equivocado!

El silicio se divide en varios bloques de construcción para la funcionalidad. Temporizadores, IO, SRAM, generador de reloj, núcleo de ejecución. El mundo integrado considera estos periféricos . Me equivoqué constantemente, asumiendo que los periféricos eran cosas conectadas al exterior de la MCU, ya que, bueno, eso es lo que son en una computadora de escritorio.

Lo que esto significa, en muchos casos, es que cuando el AVR se va a dormir, apagará estas otras partes del silicio. Los primeros en irse son algunos temporizadores, seguidos quizás por el generador de reloj principal. El rápido apagado y arranque de estos periféricos significa que los microcontroladores entran y salen constantemente de varios estados de suspensión, al contrario de un gran SUEÑO, NO SUEÑO como una computadora de escritorio. Un ejemplo de pseudocódigo que hace una docena de suposiciones incorrectas, de una comunicación en serie ficticia:

// bad, the loop burns CPU time for no benefit
int message = 2830;
int counter = 0;
while (counter++ < 32) {
    sendBit(PIN_TX, message & (2 << counter));
    _delay_us(2500); // cpu spinwait is here
}

// better, uses sleeps
int message = 2830;
int counter = 0;

function sendData() {
    sendBit(PIN_TX, message & (2 << counter++));
    if (counter >= 32)  
         TIMER_A = DISABLED;
}

TIMER_A = TIMER_INCREMENT | TIMER_OVERFLOW_CALLBACK | ONE_PER_MICROSECOND;
TIMER_A_MAX = 2500;
TIMER_A_CALLBACK = &sendData;
DEFAULT_POWERSTATE = SLEEP3;

Nuevamente, tendrá que perdonar el vago código handwavey. La idea aquí es que la comunicación en serie tiene que esperar un número determinado de microsegundos entre bits, y hay dos formas de hacerlo. Uno es por un spinwait, el otro es interrupciones. Una interrupción permitirá que la MCU atienda otras interrupciones mientras espera, o si no sucede nada, se apagará a un modo de suspensión más bajo. El equivalente correspondiente en el desarrollo de software es generar un hilo frente a while (verdadero);

Muy poco de esto responde a su pregunta original, y lo escribo como una respuesta para ayudar a adjuntar información adicional sobre cómo el sueño puede afectar a los microcontroladores de maneras que no son necesariamente intuitivas para los desarrolladores de software.

editar:

Para lograr el ciclo de activación que está preguntando, se vería algo como lo siguiente:

function buttonPress() { _set_power_mode(FULL); }

void main() {
    while (true) {
        _set_power_mode(SLEEP2);
        // button press logic here
    }
}   

Así es vagamente como recuerdo que funcionaba mi MSP430, y considerando todo, los microcontroladores tienden a seguir aproximadamente las mismas reglas. _set_power_mode de un sueño lo suficientemente profundo fue una llamada de bloqueo. Fiel al espíritu de cómo suelen ser mis proyectos, el AVR probablemente lo haga de manera completamente diferente y mi respuesta es totalmente discutible.

Entonces, ¿es posible escuchar la interrupción de un botón mientras el dispositivo está inactivo o necesito salir periódicamente del modo inactivo?
Actualizaré mi publicación, verifique en unos minutos.
está bien, lo tengo funcionando. Tenía el isr funcionando bien, pero no se activaba desde el modo de suspensión, pero sí lo hacía un pin diferente. algo sobre la escucha de borde vs nivel.