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

3

Lo siento por cualquier noobiness, soy más un ingeniero de software.

¿Cómo uso las interrupciones de botones en general?

Al igual que en, si pongo mi microcontrolador en reposo, me gustaría un botón para activarlo.

¿Cómo debo hacer para 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 moviendo 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 del ISR.

    
pregunta Funkodebat

2 respuestas

2

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

Un botón de empuje de \ $ \ overline {\ mathsf {RESET}} \ $ a tierra es la forma más fácil, pero se olvida por completo del estado actual.

Interrupciones

Para que funcionen las interrupciones, necesita un pin que se atribuya como INTn y para ATmega32 está limitado a PB2 , PD2 o 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:

  • Habilite la interrupción en el Registro de control de interrupción general GICR ;
  • Revise los bits de Control de detección de interrupción en MCUCR y MCUCSR .

No es necesario que agregue una ISR completa (rutina de servicio de interrupción) si todo lo que quiere hacer es despertarse y continuar donde lo dejó, pero no debe confiar en el vector predeterminado. Depende del compilador lo que realmente sucede en una mala interrupción. Consulte aquí para obtener el nombre del vector de interrupción que debe usar.

ISR() { INT0_vect , EMPTY_INTERRUPT };

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

Para que un botón se base en el código PD2 ( INT0 ) puede verse un poco como este (sin probar):

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
    
respondido por el jippie
2
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.

    
respondido por el Bryan Boettcher

Lea otras preguntas en las etiquetas