Forum: Compiler & IDEs Verständnisproblem


von Sandmännchen (Gast)


Lesenswert?

Also wollte mal wieder ein wenig herumspielen mit WinAVR udn ein kleines
Programm schreiben, welches folgendermaßen aussieht

(die verwendete UART.c hab ich nicht inkludiert, da diese mit dem
Problem denke ich nichts zu tun hat)


int main(void)
{
  init_uart();
  unsigned int wert,overflows,timerstand = 0;
  unsigned char buffer[10];


  uart_puts("Controller online.....  OK\n\r");

  TCCR0 = _BV(CS00) | _BV(CS02);  //1024 prescaler
  TIMSK = _BV(TOIE0);       //Timer0 Overflow Interrupt Enable
  sei(); // enable all interrupts

  while(1)
  {
    if(wert == 10)
    {
      uart_puts("Timerstand:");
      itoa(timerstand,buffer,10);
      uart_puts(buffer);
      wert = 0;
    }


  }



  ISR(TIMER0_OVF_vect)
  {

      overflows++;
      timerstand = TCNT0;

      if(overflows == 256)
      {
        wert++;
        uart_puts("Wert wurde um 1 erhöht!");
      }

  }

}


Das ich hier den Timerstand ausgebe, ist natürlich Unsinn und hat keine
spezielle Funktion. SOllte nur zum Testn sein..

Im main programm sollte in der Endlosschleife der leztzte erfasste
TImerstand rausgesendet werden.
Die if  Abfrage in der ISR und im Main Programm sollten nur eine
Verzögerung bewirken, d.h. das der Timer öfter überlaufen muss, um ein
wenig Zeit zu gewinnen....


Tatsache ist, dass der Timerstand NIE ausgegeben wird, das Programm
hängt jedoch in einer Endlosschleife, wo es nicht sollte.. denn es wird
der String "Controller online.....  OK    (sollte nur einmal bei Beginn
gesendet werden) in einer Endlosschleife rausgeschickt und sonst gar
nichts...

Ich nehme an, es ist wieder ein typischer Anfängerfehler, jedoch komm
ich nicht dahinter...

Danke im Voraus!

von Sandmännchen (Gast)


Lesenswert?

P.S.: Ich habe den Verdacht, dass da irgendwas wegoptimiert wird?! Muss
ich da irgendwo ein "static volatile" oder sowas in der Art
benutzen??

Und warum läuft der in einer "anderen" Endlosschleife?!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

"timerstand" sollte in der Tat volatile sein, da er zwischen einer
ISR
und dem Hauptprogramm Daten austauscht.

Du hast versucht, eine ISR innerhalb einer Funktion geschachtelt zu
definieren.  Bitte definiere sie auf der obersten Ebene.

von Sandmännchen (Gast)


Lesenswert?

Eine ISR innerhalb einer Funktion geschachtelt zu definieren? Wie ganau
meinst du das?

Das die ISR in der Funktion main() steht ?
Sollte die ISR vor dem main() stehen?

Was ich noch wissen möchte, in welcher Reihenfolge beginnt der Compiler
beim Übersetzen? Ich dachte immer bei main().....

Denn wenn ich z.B.: die ISR

ISR(interrupt)
{

...

}

Außerhalb von main() schreibe, bekomme ich Fehler, dass er bestimmte
Variablen nicht kennt... Wenn das main Programm aber schon übersetzt
wurde, müsste er die doch Variablen kennen....?!

Wie ist das dann, wennd die ISR vor dem Hauptprogramm steht?!

Danke!

von Marian (Gast)


Lesenswert?

Ja du solltest sie vor der Main definieren. Und damit er auch dann die
Variablen kennt, definiere sie als globale volatile Variablen.

Eigentlich sollte man doch alle Funktionen vor der Main definieren oder
nicht?

Gruß Marian

von Stefan K. (_sk_)


Lesenswert?

Variablen, die im IR benutzt werden, müssen global declariert werden,
d.h. sie müssen ausserhalb einer Funktion (in Deinem Fall main) stehen.

Variablen, die innerhalb einer Funktion stehen, werden auf dem Stack
angelegt. Die Stackadresse kann aber bei jedem Aufruf der Funktion
unterschiedlich sein. Deine Interrupt-Funktion "weiss" also nicht, an
welcher Adresse die Variable steht.

Was bei Dir auch fehlt, ist die Declaration als volatile. Siehe diverse
BEschreibungen dazu hier im Forum.


Probier Deinen Code so umzubauen:

//*** Variablendeklaration ausserhalb einer Funktion: ****
volatile unsigned int wert,overflows,timerstand = 0;
volatile unsigned char buffer[10];

int main(void)
{ .... }

ISR(TIMER0_OVF_vect)
{ .... }


Gruß, Stefan

von Winne (Gast)


Lesenswert?

ISR im Besonderen, sonst kann man sie nur während der Laufzeit der
Funktion in der sie definiert sind erreichen. Das dürfte zum sicheren
Absturtz führen , wenn der IRQ mal eben vorher vorbeikommt.
;-)

von peter dannegger (Gast)


Lesenswert?

Bin noch nie auf die Idee gekommen, Funktionen innerhalb von Funktionen
zu definieren.

Wer mit Assembler angefangen hat, macht sowas nicht, denn da gehts
definitiv schief.

Wußte garnicht, daß sowas überhaupt geht.

Warscheinlich wird dann die Funktion nicht mehr als Interrupthandler
erkannt, denn für einen freigegebenen Interrupt ohne Handler ist es
typisch, daß das Programm immer wieder von vorne anfängt.


"Was ich noch wissen möchte, in welcher Reihenfolge beginnt der
Compiler beim Übersetzen? Ich dachte immer bei main()....."

Nein.

Er übersetzt immer von oben nach unten und von links nach rechts bzw.
entsprechend den Vorrangregeln.


Peter

von Sandmännchen (Gast)


Lesenswert?

Ok, alles klar...Danke für alle Antworten, werde das heute ändern und
nochmal probieren!

Thx!

von Heinrich (Gast)


Lesenswert?

Ok, nach diesen Umstellungen/Korrekturen läuft alles so , wie ich mir
das gedacht habe!

Jetzt werd ich mich noch damit beschäftigen, wie ich genaue delays
(z.B.: genau eine schöne sekunde lang) erzeuge und was für timermodi es
alles gibt bzw. wo man die einsetzt! Das mit dem capture/compare oder
CTC mode ist mir noch zu hoch ;-)

Ein Danke an alle

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.