La respuesta de
jippie tiene los detalles técnicos, pero es posible que no entiendes los modos de suspensión de los AVR. Los microcontroladores operan en un reino diferente al que estamos acostumbrados a las computadoras de escritorio que funcionan, y de hecho combinan algunas de las mismas palabras para significar cosas que los desarrolladores de software no esperan.
Lo siguiente es lo que he reunido, como un tipo de software a mí mismo. ¡Agradezco sinceramente las modificaciones a mi publicación para corregir las cosas que me han 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 estaban conectados al exterior de la MCU, ya que, bueno, eso es lo que están en una computadora de escritorio.
Lo que esto significa, en muchos casos, es que cuando el AVR se va a dormir, cerrará estas otras partes del silicio. Los primeros en ir son algunos temporizadores, seguidos quizás por el generador de reloj principal. El rápido apagado y la puesta en marcha de estos periféricos significa que los microcontroladores están constantemente entrando y saliendo de varios estados de suspensión, al contrario de lo que ocurre en un SUEÑO grande, NO SUEÑO como una computadora de escritorio. Un ejemplo de pseudocódigo que hace una docena de suposiciones incorrectas, de una comunicación serial 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;
Una vez más, tendrás que perdonar el vago código de mano. 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. Una es por una espinera, la otra es una interrupción. Una interrupción permitirá a la MCU dar servicio a otras interrupciones mientras está en espera, o si no ocurre nada, se apagará a un modo de suspensión inferior. El equivalente correspondiente en el desarrollo de software es generar un hilo vs. 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 manera que no sean necesariamente intuitivas para los desarrolladores de software.
editar:
Para lograr el ciclo de despertar que estás 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
}
}
Esto es vagamente como recuerdo que mi MSP430 funcionaba, y considerando todas las cosas, los microcontroladores tienden a seguir aproximadamente las mismas reglas. _set_power_mode de un sueño suficientemente profundo fue una llamada de bloqueo. En espíritu fiel a cómo suelen ir mis proyectos, el AVR probablemente lo haga de manera completamente diferente y mi respuesta es totalmente irrelevante.