Forum: Mikrocontroller und Digitale Elektronik Atmega48 wacht nicht durch INT1 auf (sleep_mode(), interrupt)


von Info (Gast)


Lesenswert?

Folgender Code geht erwartungsgemäß in den Power-Down Modus, lässt sich 
dann aber durch einen low-Pegel an PD3 nicht mehr "wecken".
1
#include <stdint.h>
2
#include <avr/io.h>
3
#include <avr/wdt.h>
4
#include <avr/sleep.h>
5
#include <avr/interrupt.h>
6
7
int main(void)
8
{
9
  wdt_disable();
10
  ACSR = (1<<ACD);
11
  PORTD = 0xFF; 
12
  DDRD  = 0xFF; 
13
  TCCR0A =   0;
14
  TCCR0B = (1<<CS01);
15
  OCR0A  =  124;
16
  TIMSK0 = (1<<OCIE0A);
17
  TCCR1A =   0;
18
  TCCR1B =  (1<<CS12) | (1<<CS10);
19
  OCR0A  =   65535;
20
  TIMSK1 = (1<<OCIE1A);
21
  LEDpattern = 0;
22
  sei();
23
  while(1)
24
  {
25
    LEDpattern++;
26
    set_sleep_mode(SLEEP_MODE_IDLE);
27
    sleep_mode();
28
  }
29
}
30
31
ISR( TIMER0_COMPA_vect ) 
32
{
33
  OCR1A += 124;
34
  PORTD = LEDpattern;
35
}
36
37
ISR( TIMER1_COMPA_vect ) 
38
{
39
  PORTD  = 0xFF;
40
  DDRD  &= ~(1<<PD3);
41
  EICRA = 0;
42
  EIFR = 0;
43
  EIMSK = (1<<INT1);
44
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
45
  sleep_mode();
46
}
47
48
ISR( INT1_vect ) 
49
{
50
  EIMSK = 0;
51
  DDRD  |= (1<<PD3);
52
  PORTD  = 0x00;
53
}

Es ist vermutlich der Aufruf von sleep_mode() im interrupt - wieso?

http://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html
http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf

von Denis (Gast)


Lesenswert?

Überleg mal was als erstes, beim Anspringen der Interrupt routine 
passiert,
dann weist du auch warum bei dir keine weiteren Interrupte auftreten ...

von Pandur S. (jetztnicht)


Lesenswert?

Aaaaahhhhhhh....

ein sleep() in einem timer interrupt ....

von Info (Gast)


Lesenswert?

Denis schrieb:
> was als erstes, beim Anspringen der Interrupt routine
> passiert,

Meinst du einen spezifischen? In beiden schalte ich den Interrupt aus, 
den Pin um, und den anderen Interrupt ein. Wo genau ist das Problem?

Jetzt N. schrieb:
> Aaaaahhhhhhh....
>
> ein sleep() in einem timer interrupt ....

Genau das ist die Frage: ist das das Problem, und wieso? Du musst es mir 
ja nicht erklären, aber hilfreicher wäre ein Verweis!

von Peter D. (peda)


Lesenswert?

Der AVR nimmt zum Aufwachen die Interruptlogik.
D.h. bei globaler Interruptsperre kann er nicht aufwachen.

von Info (Gast)


Lesenswert?

Aha, danke! Schon lange nichts mehr mit AVR gemacht (Gruß in den 
Wedding).
1
7.7 Reset and Interrupt Handling
2
...
3
When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled. The user 
4
software can write logic one to the I-bit to enable nested interrupts. All enabled interrupts can then interrupt the 
5
current interrupt routine. The I-bit is automatically set when a Return from Interrupt instruction – RETI – is 
6
executed. 
7
8
...
9
10
if one or more interrupt conditions occur while the Global 
11
Interrupt Enable bit is cleared, the corresponding Interrupt Flag(s) will be set and remembered until the Global 
12
Interrupt Enable bit is set, and will then be executed by order of priority. 
13
14
..
15
16
When the AVR exits from an interrupt, it will always return to the main program and execute one more 
17
instruction before any pending interrupt is served.

von Pandur S. (jetztnicht)


Lesenswert?

Ein interrupt muss immer sofrt zu Ende ausgefuehrt werden. Ein sleep 
kommt immer, ausschliesslich, und genau einmal in den Endlosloop des 
main()

von Peter D. (peda)


Lesenswert?

Du kannst ja nur das "set_sleep_mode(SLEEP_MODE_PWR_DOWN);" im Interrupt 
lassen, darfst es dann aber in der Mainloop nicht sofort wieder 
rücksetzen.

Das "sleep_mode();" sollte man generell nicht verwenden, es bewirkt eine 
Race Condition (siehe Erläuterung in <sleep.h>).

von Info (Gast)


Lesenswert?

OK, danke.

Habe zwischenzeitlich die set_sleep_mode() in die jeweiligen ISRs 
gesetzt und in der Endlosschleife (noch) das sleep_mode().

1
    As the \c sleep_mode() macro might cause race conditions in some
2
    situations, the individual steps of manipulating the sleep enable
3
    (SE) bit, and actually issuing the \c SLEEP instruction, are provided
4
    in the macros \c sleep_enable(), \c sleep_disable(), and
5
    \c sleep_cpu().  This also allows for test-and-sleep scenarios that
6
    take care of not missing the interrupt that will awake the device
7
    from sleep.
8
9
    Example:
10
    \code
11
    #include <avr/interrupt.h>
12
    #include <avr/sleep.h>
13
14
    ...
15
      set_sleep_mode(<mode>);
16
      cli();
17
      if (some_condition)
18
      {
19
        sleep_enable();
20
        sei();
21
        sleep_cpu();
22
        sleep_disable();
23
      }
24
      sei();
25
    \endcode
26
27
    This sequence ensures an atomic test of \c some_condition with
28
    interrupts being disabled.  If the condition is met, sleep mode
29
    will be prepared, and the \c SLEEP instruction will be scheduled
30
    immediately after an \c SEI instruction.  As the intruction right
31
    after the \c SEI is guaranteed to be executed before an interrupt
32
    could trigger, it is sure the device will really be put to sleep.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.