Forum: Compiler & IDEs ATMEGA48 Interrupt


von Hans (Gast)


Lesenswert?

Hallo,

ich hab ein kleines Problem mit den Interrupts bei meinem Atmega48.
Und zwar sprinngt mir das Programm nach einem Timerinterrupt nicht mehr
zurück in die main Funktion. Ist das normal?
Ich hab auch schon versucht mit reti() wieder zurück zu springen, aber
dann land ich wieder ganz am Anfang von main, also noch vor der
Initialisierung der Timer und Interrupts. Das ist dann auch nicht Sinn
der Sache.
Gibt es da eine andere Lösung oder muss ich mich irgendwie von Interrupt
zu Interrupt durchmogeln?

Was passiert eigentlich wenn ein Interrupt von einem Anderen
unterbrochen wird? Hab keine Prio für die Interrupts gefunden. Vor allem
springt er dann wenigstens in die unterbrochene Funktion zurück oder ist
da dann das gleiche Problem?

Danke im Voraus für die Mühe


p.s. ich programmier in C mit avrstudio 4

von Fred S. (Gast)


Lesenswert?

Hi Hans,

ohne Code wird das nur ein Ratespiel. Deine Fragen versuche ich trotzdem 
mal zu beantworten:

> Und zwar sprinngt mir das Programm nach einem Timerinterrupt nicht mehr
> zurück in die main Funktion. Ist das normal?
Das hängt davon ab, was in der ISR steht (z.B. eine Endlosschleife?).

> Ich hab auch schon versucht mit reti() wieder zurück zu springen, aber
> dann land ich wieder ganz am Anfang von main, also noch vor der
> Initialisierung der Timer und Interrupts.
"reti" solltest Du in einer ISR in C auch nicht hinzufügen.

> Gibt es da eine andere Lösung oder muss ich mich irgendwie von Interrupt
> zu Interrupt durchmogeln?
Durchmogeln? Der uC macht nur, was Dein Programm ihm sagt.

> Was passiert eigentlich wenn ein Interrupt von einem Anderen
> unterbrochen wird? Hab keine Prio für die Interrupts gefunden.
Verwendest Du "ISR()"? Dann wird nichts unterbrochen. Wenn während der 
ISR ein weiterer Interrupt gesetzt wird, kehrt das Programm zunächst zu 
dem Punkt+1 zurück, wo es unterbrochen wurde, dann zur zweiten ISR.

Mehr kann ich ohne Code nicht helfen.

Gruß

Fred

von Hans (Gast)


Lesenswert?

Danke Fred

im code steht eignetlich noch nix interresantes drin. also nur die paar 
haeder, die main funktion, eine init() zur Belegung der register für 
Timer und Interrupts und die paar ISR() Funktionen.

int Zeitbasis;

int main(void){
 init();

 while(1)
 {
   // hier solln noch viel entstehn :)


   while(Zeitbasis < 98){}  // warten bis 10 ms vergangen sind

   // HIER KOMM ICH NICHT MEHR HIN
   Zeitbasis = 0;
 }
return 0;
}

ISR(TIM0_vect){
 Zeitbasis++;
}

die init() und die header spar ich mir mal, sind ja normal standard

von Sven P. (Gast)


Lesenswert?

Selbes Spiel wie immer: Der Optimierer...

von Fred S. (Gast)


Lesenswert?

Hallo Hans,

nur eben mal auf die Schnelle:
1. Wo ist denn Dein TIM0_vect definiert? Welche WinAVR Version 
verwendest Du? Für den ATmega48 kenne ich nur die folgenden 
Timer0-Interrupt-Vektoren:
  TIMER1_OVF_vect
  TIMER0_COMPA_vect
  TIMER0_COMPB_vect
  TIMER0_OVF_vect
2. Zeigst Du uns bitte die Initialisierung des Timers?

Viele Grüße

Fred

von Hans (Gast)


Lesenswert?

hast recht

hab den code ausm Gedächtnis geschrieben, heißt natürlich 
TIMER0_OVF_vect und steht in iomx.h

TCCROA=0x00;
TCCR0B=0x02;  //2500kHz
TCNT0=0X00;
OCR0A=0x00;
OCR0B=0x00;

TIMSK0=0x01;


hab aber auch schon viel langsamer versucht, hat auch nix gebracht

von Johannes M. (johnny-m)


Lesenswert?

Zeitbasis ist nicht volatile deklariert, wird aber in main und in der 
ISR benutzt. Da wird der Optimizer reinhauen...

BTW: Nächstes Mal bitte nur einmal posten...

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Zusätzlich zu den Fragen von Fred S. fällt mir das fehlende volatile 
bei int Zeitbasis; auf. Ohne volatile Kennzeichnung geht der Compiler 
davon aus, dass sich Zeitbasis in main nie ändert. Möglicherweise 
hat Sven Pauli das gemeint mit dem Optimierer.

> die init() und die header spar ich mir mal, sind ja normal standard

Standard hin oder her. Den obenstehenden Code kann man jedenfalls nicht 
in der eigenen Toolchain übersetzen oder für den Atmega48 simulieren. 
Aber wie du meinst - du suchst Hilfe, nicht "wir" ;-)

von Hans (Gast)


Lesenswert?

die init ist mit der Timerkonfiguration eigentlich schon fast komplett, 
da fehlt nur noch sei();
und Zeitbasis=0;

zu den Headern

<stdint.h>
<avr/interrupt.h>
<avr/io.h>
<inttypes.h>

wo muss das volatile eigentlich genau hin hab alle positionen 
ausprobiert, ohne Erfolg.

Zeitbasis wird auch hochgezählt, es zählt aber über die 98 drüber ohne 
aus der while zu fliegen

von Stefan E. (sternst)


Lesenswert?

> wo muss das volatile eigentlich genau hin hab alle positionen
> ausprobiert, ohne Erfolg.

In die Deklaration:
volatile int Zeitbasis;

> Zeitbasis wird auch hochgezählt, es zählt aber über die 98 drüber ohne
> aus der while zu fliegen

Bitte poste mal den echten Code, entweder als Anhang oder per 
Cut&Paste, und keine aus dem Gedächtnis hingeschriebene Fragmente.

von Hans (Gast)


Lesenswert?

#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <inttypes.h>

volatile int  Zeitbasis;

void init()
{

//Variablen initialisieren
  Zeitbasis=0;



//Timer 0

  TCCR0A=0x00;
  TCCR0B=0x02;
  TCNT0=0x00;
  OCR0A=0x00;
  OCR0B=0x00;

  TIMSK0=0x01;

  sei();

}

int main (void)
{
   init();


  while(1)
  {


    while(Zeitbasis < 98)
     {
    }


  }

return 0;
}

ISR (TIMER0_OVF_vect)
{
  Zeitbasis++;

}

von Fred S. (Gast)


Lesenswert?

Hallo Hans,

die Deklaration und Verwendung von "Zeitbasis" ist in Ordnung. Woran 
kannst Du aber überhaupt erkennen, dass der Programmzeiger in der ISR 
stecken bleibt, wie Du im ersten Posting geschrieben hast?

Übrigens: Schöner wäre es, wenn Du den Code mit symbolischen Bitnamen 
und Kommentaren schriebst, z.B.:
1
TCCR0B=1<<CS01; // F_CPU/8 = 2,5MHz

Gruß

Fred

von Stefan B. (stefan) Benutzerseite


Angehängte Dateien:

Lesenswert?

Passt. In der Simulation funktioniert der Code (er macht nur nicht 
viel).
1
#include <stdint.h>
2
#include <avr/interrupt.h>
3
#include <avr/io.h>
4
#include <inttypes.h>
5
6
volatile int Zeitbasis;
7
8
void init()
9
{
10
  //Variablen initialisieren
11
  Zeitbasis=0;
12
13
  //Timer 0
14
  TCCR0A=0x00;  // Normal Mode
15
  TCCR0B=0x02;  // 0x02 = (1<<CS01) = Prescaler 8
16
  TCNT0=0x00;   // 0..255
17
  OCR0A=0x00;   // unwichtig da Normal Mode
18
  OCR0B=0x00;   // unwichtig da Normal Mode
19
  TIMSK0=0x01;  // 0x01 = 1<<TOIE0)
20
21
  sei();
22
}
23
24
int main (void)
25
{
26
  init();
27
28
  while(1)
29
  {
30
    // F_CPU in MHz  Schleifendauer
31
    // 1             201  ms          
32
    // 8             25   ms      
33
    // 16            12,5 ms      
34
    while(Zeitbasis < 98)
35
     {
36
     }
37
38
    // Zeitbasis zurücksetzen
39
    cli(); // Interrupts sperren
40
    Zeitbasis = 0; 
41
    sei(); // Interrupts freigeben
42
43
    PORTD ^= (1<<PD1); // zu meiner Info, weil sonst nicht viel passiert
44
  }
45
46
  return 0;
47
}
48
49
50
ISR (TIMER0_OVF_vect)
51
{
52
  // F_CPU in MHz  Aufruf ca. alle                          (EDIT)
53
  // 1             2 ms                 1/(1000000 / 8 / 256)  Sekunden
54
  // 8             0,256 ms             1/(8000000 / 8 / 256)  Sekunden
55
  // 16            0,128 ms             1/(16000000 / 8 / 256) Sekunden
56
  Zeitbasis++;
57
}

von Hans (Gast)


Lesenswert?

ich hab einen Haltepunkt im Interrupt und beobachte wie die zeitbasis 
hochgezählt wird.

OHH mist mir ist bei der ganzen testerrei eine codezeile verloren 
gegangen.

nach der while ( Zeitbasis <98){}
 war mal
Zeitbasis = 0;

ok dann wars doch das volatile

danke an alle, war echt super von euch


nur noch eine kleine frage wenn ich schonmal dabei bin. Muss ich 
operationen iin der ISR vor Unterbrechungen schützen z.b. mit atomic?

von Fred S. (Gast)


Lesenswert?

Hallo Hans,

na also -- ging doch!

> nur noch eine kleine frage wenn ich schonmal dabei bin. Muss ich
> operationen iin der ISR vor Unterbrechungen schützen....

Nein, ist bei der ISR nicht nötig... es sei denn, Du hast ein ein 
"sei();" in der ISR!

Gruß

Fred

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Nein, du musst aber beim Zurücksetzen von Zeitbasis Unterbrechungen 
verhindern. Ich habe es gerade in das Listing eingebaut.

von Hans (Gast)


Lesenswert?

OK es scheitert halt immer an Kleinigkeiten ;)

Also danke nochmal

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.