Forum: Mikrocontroller und Digitale Elektronik Interrupt Routine stoppt die Ausführung


von Roman G. (roman76aut)


Lesenswert?

Hallo Leute,

ich habe folgendes einfaches Programm für meinen Atmega328p:
1
#define F_CPU 16000000UL
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
#include <avr/interrupt.h>
6
7
8
9
void main (void) {
10
    DDRD = (1<<PD3);
11
    DDRB = (1<<PB0);
12
    cli();
13
    TCCR2A = (1<<WGM21) | (1<<WGM20) | (1<<COM2B1);
14
    OCR2B = 0;
15
    TIMSK2 = 0x01;
16
    sei();
17
  TCCR2B = (1 << CS20);
18
  
19
  while(1){
20
    //PORTD ^= (1<<PD3);
21
    PORTB ^= (1<<PB0);
22
    _delay_ms(1000);
23
    OCR2B +=10;
24
    //PORTD ^= (1<<PD3);
25
    PORTB ^= (1<<PB0);
26
    _delay_ms(1000);
27
  
28
  }
29
}
30
31
/*
32
ISR (TIMER2_OVF_vect)
33
{
34
  _delay_ms(1000);
35
  reti();
36
}
37
38
*/
Ein shell Skript erstellt und sendet das Programm:
1
echo "Compiler Object"
2
avr-gcc -c -Os -mmcu=atmega328p -o SimpleIO.o SimpleIO.c
3
echo "Compiler ELF"
4
avr-gcc SimpleIO.o -o SimpleIO.elf
5
echo "Compiler HEX"
6
avr-objcopy -O ihex -j .data -j .text SimpleIO.elf SimpleIO.hex
7
echo "AVRDUDE"
8
sudo avrdude -patmega328p -P usb -cusbasp-clone -Uflash:w:SimpleIO.hex:a

Wenn ich die ISR auskommentiert lasse wie oben, dann funktioniert es das 
PB0 blinkt und PD3 mittels Fast-PWM in 10er Schritten alle zwei Sekunden 
hochgezählt wird.

Sobald ich ISR verwende (egal ob mit delay, reti() oder leer) bleiben 
alle LED dunkel. Bisher konnte ich es also auf die Existenz der ISR 
zurück führen.

Bitte um eure Hilfe da ich dieses Problem noch nicht im Netz gefunden 
habe.

Danke im voraus,
Roman

von Kurt B. (kurt-b)


Lesenswert?

Roman G. schrieb:

> Sobald ich ISR verwende (egal ob mit delay, reti() oder leer) bleiben
> alle LED dunkel. Bisher konnte ich es also auf die Existenz der ISR
> zurück führen.

Wartest du in der IR 1 Sekunde lang bis du zurückspringst?


 Kurt

von MWS (Gast)


Lesenswert?

Ist doch klar, der µC  triggert die ISR schneller, als deren Laufzeit 
beträgt. Somit ist das Ding immer in der ISR und kommt vielleicht pro 
ISR-Ausführung 1 Takt in der Hauptschleife weiter. Eine Wartesekunde in 
der Hauptschleife kostet 16000000 Takte, d.h. nach ca. 185 Tagen wird 
die LED zu leuchten beginnen :D
Musst nur etwas länger aufbleiben.1

von Roman76aut (Gast)


Lesenswert?

Hab es auch als leere routine versucht. Eigentlich ist mein problem, 
dass mit isr nix geht.

von Roman76aut (Gast)


Lesenswert?

Also:

ISR (TIMER2_OVF_vect)
{
}

von MWS (Gast)


Lesenswert?

Falsches Target?

von Carl D. (jcw2)


Lesenswert?

Wenn deine ISR aktiv ist, dann wird sie praktisch dauerhaft aktiv sein.
Das delay(1000) sorgt dafür, daß nach RETI() schon der nächste Int 
ansteht. In so einem Fall führt ein AVR genau einen Befehl in der 
Hauptschleife aus, bevor wieder die ISR dran ist. Und ein delay(1000) in 
der Hauptschleife muß 1..20 Millionen Taktzyklen "vernichten", von denen 
dann aber nur einer je Sekunde ausgeführt wird. Dauert also etwas 
länger!
Zudem wird Reti() dafür sorgen, daß je ISR-Aufruf einige Bytes auf dem 
Stack liegen bleiben. Nach einiger Zeit endet das bestenfalls in einem 
"Soft-Reset".

Also:
- ISR() braucht kein reti(), das macht es schon selbst
- delay() in ISR ist böse, denn
- delay() in Mainloop erwartet, daß die geplanten Takt auch von der
  Mainloop ausgeführt werden. Werden 50% davon in der ISR ausgeführt,
  dann dauert das delay doppelt so lang. Werden 99.999% der Takte in der
  ISR ausgeführt, dann ...

von MWS (Gast)


Lesenswert?

> reti();

Du umgehst das normale POPen der Register, nimm das raus, das ist 
Unsinn.

von Carl D. (jcw2)


Lesenswert?

Gerade in anbetracht der Programmgröße:
Wirf einen Blick ins .lss File, da kann man sehen, wie falsch einem der 
Compiler verstanden hat. (Wobei er es in konkreten Fall sehr einfach 
hatte. Das Falschverstehen.)

von Roman G. (roman76aut)


Lesenswert?

MWS schrieb:
> Falsches Target?

Ich habe auch eine Vermutung das irgend eine Compiler Option diesen 
Effekt bewirkt. Welches wäre das richtige Target?

Kann sich jemand mein sh ansehen bzgl. der Optionen?

MWS schrieb:
> Eine Wartesekunde in
> der Hauptschleife kostet 16000000 Takte, d.h. nach ca. 185 Tagen wird
> die LED zu leuchten beginnen :D

Mit ist klar das dieser delay Unsinn ist. Eigentlich hatte ich auch noch 
die Led zum Toggeln drinnen. Etwas so:
1
ISR (TIMER2_OVF_vect)
2
{
3
  _delay_ms(1000);
4
  PORTB ^= (1<<PB0);
5
}
Später hab ich auch geschrieben das ich die ISR leer hatte und trotzdem 
das Problem aufgetaucht ist.
Eigentliches Ziel ist im Interrupt einfach eine Zählervariable zu 
erhöhen.
1
ISR (TIMER2_OVF_vect)
2
{
3
  someCounter++;
4
}

lg
Roman

von Carl D. (jcw2)


Lesenswert?

> Wenn ich die ISR auskommentiert lasse wie oben, dann funktioniert es das
> PB0 blinkt und PD3 mittels Fast-PWM in 10er Schritten alle zwei Sekunden
> hochgezählt wird.

Die "auskommentierte ISR", bei eingeschaltetem Timer2OverflowInterrupt 
sorgt für einen Neustart bei Überlauf des Timer2. Das führt auch zu 
"LED-Flackern", aber nicht zum gewünschten Programmablauf. Troll?

von Roman G. (roman76aut)


Lesenswert?

Carl D. schrieb:
> Die "auskommentierte ISR", bei eingeschaltetem Timer2OverflowInterrupt
> sorgt für einen Neustart bei Überlauf des Timer2. Das führt auch zu
> "LED-Flackern", aber nicht zum gewünschten Programmablauf. Troll?

Led flackern hab ich auch gesehen, kann mich aber nicht mehr erinnern in 
welchem Status da ich vieles ausprobiert habe. Kann gut sein dass ich 
auch die Timer Mask auskommentiert hatte um die PWM Funktion zu sehen.
Warum geht nix wenn ich ISR aktiv habe? Zumindest flackert die Led wenn 
der Timerüberlauf resetet. Hatte ich bisher nicht gewußt aber es zeigt 
immerhin das der µC bis dahin richtig funktioniert.

von neuer PIC Freund (Gast)


Lesenswert?

Für ein besseres Aha-Erlebnis:

Benutze das Atmel Studio mit dem Simulator.

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.