Forum: Mikrocontroller und Digitale Elektronik Tiny45 Interrupt wird in ISR nicht wieder eingeschaltet


von concept (Gast)


Lesenswert?

Wieder ein Problem

Grob das Programm:

TIMSK = 1<<OCIE0A;
MCUCR = 0;
GIMSK = 1<<PCIE;
PCMSK = 1<<PCINT2;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sei();
sleep_mode();

die main loop ist leer.

Taste gedrückt.

ISR(PCINT0_vect)
{
  GIMSK &= ~(1<<PCIE);
}

Dann nudelt das Programm, in einer Timer-ISR ist dann Schluss

GIMSK |= (1<<PCIE);
sleep_mode();

Aber der PCInterrupt wird anschließend nicht mehr ausgeführt.

Gibt es da irgendwelche Einschränkungen, dass man das Register nicht aus 
einer ISR schreiben kann oder so?

von FBI (Gast)


Lesenswert?

Hi,

Du solltest Dich nochmal mit der Funktionsweise von Interruptroutinen 
beschäftigen!
Während einer Interruptroutine sind alle weiteren Interrupts gesperrt 
und werden erst wieder beim Verlassen freigegeben (RETI in ASM). Wenn Du 
also deinen Controller innerhalb der Interruptroutine schlafen legst 
hast Du verloren.
Schmeiß das "sleep_mode();" aus Deinem Timerinterrupt und verschiebe 
selbiges aus main in die Endlosschleife.

CU

von Willi W. (williwacker)


Lesenswert?

Oder mach es manuell, ich glaube STI oder so ähnlich heißt der Befehl. 
Die Lösung von FBI ist aber die bessere.

von Rolf Magnus (Gast)


Lesenswert?

> Oder mach es manuell, ich glaube STI oder so ähnlich heißt der Befehl.

Du meinst vermutlich sei(), aber innerhalb einer Interrupt-Routine 
sollte man keine Interrupts einschalten, wenn's nicht unbedingt nötig 
ist bzw. man ich über die Auswirkungen nicht 100% im Klaren ist.

von Fred S. (Gast)


Lesenswert?

Hi concept,

Deine Frage kann ich nicht gut mit dem Code in Verbindung bringen. Du 
fragst, warum der PC-Interrupt nicht ausgelöst wird. Anhand des 
geposteteten Codes würde ich sagen, weil Du PCMSK für PCINT2 
initialisierst ( PCMSK = 1<<PCINT2; ), aber keine entsprechende ISR, 
sondern nur eine für PCINT0 ( ISR(PCINT0_vect) ) verwendest. Um Deine 
Verwendung von "sleep()" im Power-Down Modus zur verstehen, brauchte man 
mehr vom Programm. Aber vielleicht findest Du mit meiner obigen 
Anmerkung das eigentliche Problem. Lass doch zunächst mal alle "sleep()" 
usw. Befehle weg.

Gruß

Fred

von concept (Gast)


Lesenswert?

ARGH!

> Während einer Interruptroutine sind alle weiteren Interrupts gesperrt
> und werden erst wieder beim Verlassen freigegeben (RETI in ASM). Wenn Du
> also deinen Controller innerhalb der Interruptroutine schlafen legst
> hast Du verloren.

Danke!


@Fred
Dieser Interrupt kann von mehreren Pins ausgelöst werden.

von concept (Gast)


Lesenswert?

Leider gibt es noch ein Problem, wahrscheinlich übersehe ich wieder 
sowas Blödes :-)

TIMSK = 1<<OCIE0A;
MCUCR = 0;
GIMSK = 1<<PCIE;
PCMSK = 1<<PCINT2;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sei();
for (;;)
{
   sleep_mode();
}

ISR(PCINT0_vect)
{
   GIMSK &= ~(1<<PCIE);
   set_sleep_mode(SLEEP_MODE_IDLE);
}

ISR(TIM0_COMPA_vect)
{
  GIMSK = (1<<PCIE);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
}


Das ist auch so in etwa der Ablauf. Die Timer-ISR wird nicht mehr 
aufgerufen, daher gehe ich davon aus, dass er wirklich im PWR_DOWN ist.
Leider greift der Interrupt nicht, und er schläft immer weiter.

Sehr viel später passiert allerdings irgendetwas und er wacht wieder auf 
Knopfdruck auf. Ich kann leider nicht nachvollziehen, was das ist 
(reset?).

Aber wenn es prinzipiell so funktionieren sollte, weiß ich, dass ich den 
Fehler woanders suchen kann.

von concept (Gast)


Lesenswert?

Wird bei meinem Gefasel nicht so ganz klar: einmal nach dem Einschalten 
funktioniert das Ganze.

von Rolf Magnus (Gast)


Lesenswert?

Der Timer wird nirgends gestartet. Aber mal abgesehen davon: Woher weißt 
du eigentlich, daß die Timer-ISR nicht aufgerufen wird?

von concept (Gast)


Lesenswert?

Hi,
der Timer wird vor den Codeausschnitten gestartet, und läuft mit 32kHz. 
Im Timerinterrupt schalte ich einen Pin ein und aus.

Ich habe mittlerweile das Programm komplett leergemacht, die Beschaltung 
sicherheitshalber entkoppelt, die Schaltung aus einer Batterie (3.2V) 
versorgt. Interner Takt mit 8MHz.
1
#include <avr/io.h>
2
#include <stdint.h>
3
#include <stdlib.h>
4
#include <avr/sleep.h>
5
#include <avr/interrupt.h>
6
#include <avr/pgmspace.h>
7
8
ISR(TIM0_COMPA_vect)
9
{
10
  PORTB |= 1<<PB0;
11
  GIMSK = (1<<PCIE);
12
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
13
  PORTB &= ~(1<<PB0);
14
}
15
16
ISR(PCINT0_vect)
17
{
18
  GIMSK &= ~(1<<PCIE);
19
  set_sleep_mode(SLEEP_MODE_IDLE);
20
} 
21
22
int main( void )
23
{
24
25
OSCCAL = 0x55;
26
27
PORTB = 1<<PB2;
28
DDRB = 1<<PB0;
29
30
ACSR = 1<<ACD;
31
32
TCCR0A = 1<<WGM01;
33
TCCR0B = 1 << CS00;  
34
OCR0A = 250;
35
TCCR1 = 1<<PWM1A | 1<<CS10 | 1<<COM1A1;
36
OCR1A = 0;
37
38
TIMSK = 1<<OCIE0A;
39
MCUCR = 0;
40
GIMSK = 1<<PCIE;
41
PCMSK = 1<<PCINT2;
42
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
43
sei();
44
  for (;;)
45
  {
46
    sleep_mode();
47
  }
48
}

Nach Anlegen der Versorgung messe ich an PB0 erwartungsgemäß je einen 
High-Impuls beim Drücken/Loslassen von PB2. Das Ganze funktioniert sogar 
mehrmals hintereinander, aber irgendwann ist dann Schluß - warum?

von concept (Gast)


Lesenswert?

Tja, nachdem ich den AVR ausgetauscht habe (kein Unterschied) habe ich 
noch die überflüssigen Includes gelöscht - jetzt geht's. Der Impuls bei 
einem Tastendruck ist ca. 1,2µs lang.
1
#include <avr/io.h>
2
#include <stdint.h>
3
4
#include <avr/sleep.h>
5
#include <avr/interrupt.h>
6
7
ISR(TIM0_COMPA_vect)
8
{
9
  PORTB |= 1<<PB0;
10
  GIMSK |= 1<<PCIE;
11
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
12
  PORTB &= ~(1<<PB0);
13
}
14
15
ISR(PCINT0_vect)
16
{
17
  GIMSK &= ~(1<<PCIE);
18
  set_sleep_mode(SLEEP_MODE_IDLE);
19
} 
20
21
int main( void )
22
{
23
24
PORTB  = 1<<PB2;
25
DDRB   = 1<<PB0;
26
  
27
TCCR0A = 1<<WGM01;  // CTC MODE
28
TCCR0B = 1<<CS00;  // 8MHz
29
OCR0A  = 250;    // 32000Hz
30
  
31
TIMSK  = 1<<OCIE0A;
32
33
GIMSK  = 1<<PCIE;
34
PCMSK  = 1<<PCINT2;
35
36
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
37
sei();
38
39
  for (;;)
40
  {
41
    sleep_mode();
42
  }
43
}

Dann Versuch ich jetzt mal, das Programm wieder zum Laufen zu kriegen.

von concept (Gast)


Lesenswert?

Zu früh gefreut. Es geht ein paar (3-15) Tastendrücke, aber irgendwann 
nicht mehr.
Kann mir jemand vielleicht auf die Sprünge helfen, das Problem weiter 
einzugrenzen?

Fuses:
BOD 2.0V
Int. Osc. 8MHz + 4ms

von concept (Gast)


Lesenswert?

neuer thread, da betreff nicht mehr zutreffend:
Beitrag "Tiny45 stürzt ab trotz Minimalprogramm"

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.