mikrocontroller.net

Forum: Compiler & IDEs ATMEGA48 Interrupt


Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Selbes Spiel wie immer: Der Optimierer...

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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" ;-)

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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++;

}

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.:
TCCR0B=1<<CS01; // F_CPU/8 = 2,5MHz

Gruß

Fred

Autor: Stefan B. (stefan) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Passt. In der Simulation funktioniert der Code (er macht nur nicht 
viel).

#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;  // Normal Mode
  TCCR0B=0x02;  // 0x02 = (1<<CS01) = Prescaler 8
  TCNT0=0x00;   // 0..255
  OCR0A=0x00;   // unwichtig da Normal Mode
  OCR0B=0x00;   // unwichtig da Normal Mode
  TIMSK0=0x01;  // 0x01 = 1<<TOIE0)

  sei();
}

int main (void)
{
  init();

  while(1)
  {
    // F_CPU in MHz  Schleifendauer
    // 1             201  ms          
    // 8             25   ms      
    // 16            12,5 ms      
    while(Zeitbasis < 98)
     {
     }

    // Zeitbasis zurücksetzen
    cli(); // Interrupts sperren
    Zeitbasis = 0; 
    sei(); // Interrupts freigeben

    PORTD ^= (1<<PD1); // zu meiner Info, weil sonst nicht viel passiert
  }

  return 0;
}


ISR (TIMER0_OVF_vect)
{
  // F_CPU in MHz  Aufruf ca. alle                          (EDIT)
  // 1             2 ms                 1/(1000000 / 8 / 256)  Sekunden
  // 8             0,256 ms             1/(8000000 / 8 / 256)  Sekunden
  // 16            0,128 ms             1/(16000000 / 8 / 256) Sekunden
  Zeitbasis++;
}


Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

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

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK es scheitert halt immer an Kleinigkeiten ;)

Also danke nochmal

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.