www.mikrocontroller.net

Forum: Compiler & IDEs Timer0 und Timer2 simultan - ATMega32


Autor: TKam (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

bin ein GCC noob und ich habe ein Problem, wenn ich Timer 0 und Timer 2 
simultan initialisiere.

Ich moechte Timer 0 und 2 simultan etwas rechnen lassen und konfiguriere 
sie als compare interrupts:

    //Timer 0 und Timer 2 konfigurieren
    TCCR0 = (1<<WGM01) | (1<<CS01);
    OCR0 = 2;
    TCCR2 = (1<<WGM21) | (1<<CS21);
    OCR2 = 2;
    //Compare Interrupts 0 und 2 aktivieren
    TIMSK = (1<<OCIE0) | (1 << OCIE2);

Die Interrupt-Routinen inkrementeiren lediglich jeweils einen Integer:

    ISR(TIMER0_COMP_vect)
    {
        i++;
    }

    ISR(TIMER2_COMP_vect)
    {
        j++;
    }

In meiner main gebe ich in einer Schleife die Werte von i und j auf 
meinem LCD aus:

    for(;;) {
        set_cursor(0, 2);
        itoa(i,LcdBuffer,10);
        lcd_string(LcdBuffer);//lcd_string("  ");

        set_cursor(0, 3);
        itoa(j,LcdBuffer,10);
        lcd_string(LcdBuffer);//lcd_string("  ");
    }

Das Merkwuerdige ist, dass j staendig inkrementiert wird, aber i nicht; 
i hat permanent den Wert 0.

Und jetzt kommt's: wenn ich die Kommentare lcd_string("  "); nach der 
Ausgabe von i und j wieder in den Quellcode reinnehme, wird die 
Interrupt-Routine des Timers 0 EINMAL ausgefuehrt, denn i nimmt ab dann 
konstant den Wert 1 an.

Kann mir jemand erklaeren, womit das zu tun hat? Warum wird Timer0 nicht 
korrekt ausgefuehrt? Die main.c befindet sich im Anhang.

Vielen Dank im Voraus und schoene Gruesse,
Thomas

Autor: TKam (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Nur fuer den Fall, dass ich etwas in der Makefile verhauen habe, haenge 
ich sie auch nochmal an.

Die LCD-Routinen habe ich aus dem gcc-tutorial von hier.

Autor: Magnus Müller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schon mal was von "volatile" gehört?

Autor: TKam (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank fuer die schnelle Antwort.

Ich habe mal probiert, i und j als volatile unsigned int zu deklarieren, 
aber das Problem tritt nach wie vor auf. Worin besteht denn der 
Unterschied dazu, wenn ich i und j einfach als uint8_t deklariere?

Ich bin fuer jede Hilfe Dankbar!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
* das volatile muss rein

* Wenn ich das recht sehe, dann lässt du beide Timer mit Full-Speed im 
CTC Modus laufen und setzt einen Compare Wert von 2.
Das heist aber auch, dass alle 3 Takte ein Interrupt ausgelöst wird.

D.h. Der Timer2 macht dir mit seinen Interrupts alles andere dicht. 
Sobald der Interrupt abgearbeitet ist, ist auch schon der nächste 
Interrupt von diesem Timer da. Dein Hauptprogramm schleppt sich mit Ach 
und Krach durch die Hauptschleife, praktisch ständig von der Interrupt 
Bearbeitung für Timer2 unterbrochen. Der Interrupt vom Timer0 kommt da 
gar nicht mehr durch.

Änderungen:
i und j als volatile definieren.
die OCR Werte höher setzen.

Autor: TKam (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wow, das ist ja interessant.

Ich dachte fuer Interrupt-Routinen wird (egal wo) immer unterbrochen. 
Dass sich 2 Timer wegen der Zeiten in die Quere kommen, haette ich daher 
nicht vermutet.

Aber das Hochsetzen der OCRx-Register hats echt gebracht.

Herzlichen Dank an die schnelle Hilfe, Karl heinz und Magnus, und 
schoene Gruesse!
Thomas

Autor: Tim T. (tim_taylor)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TKam schrieb:
> Ich dachte fuer Interrupt-Routinen wird (egal wo) immer unterbrochen.
> Dass sich 2 Timer wegen der Zeiten in die Quere kommen, haette ich daher
> nicht vermutet.

http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

TKam schrieb:
> Wow, das ist ja interessant.
>
> Ich dachte fuer Interrupt-Routinen wird (egal wo) immer unterbrochen.
> Dass sich 2 Timer wegen der Zeiten in die Quere kommen, haette ich daher
> nicht vermutet.

Prinzipiell ist es auch so, wie Du schreibst.
Praktisch denke einfach darüber nach, wieviel Taktzyklen nötig sind, um 
Deine Befehle zu bearbeiten und wie oft Dein Interrupt auftritt.

Auch ein AVR kann immer nur einen Befehl nach dem anderen bearbeiten,
wenn eine Interruptroutine aufgerufen wurde, ist eben niemand da, der 
sich um den IRQ des 2. Timer oder um die Bearbeitung der main kümmern 
könnte.

Gruß aus Berlin
Michael

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.