www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer OV-Interrupt von T1 und T3


Autor: Peter Pan IV (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich habe ein Problem:

In meiner Schaltung mit mega128 werkeln der Timer1 und der Timer3. Von
beiden wird der Timer-Overflow-Interrupt ausgewertet.
T1 löst ca. jede Sekunde aus und T3 löst ca. alle 10,1 Sekunden aus.

Bis auf den Interrupt von T1 klappt alles. Denn dieser Interrupt wird
ab und zu nicht ausgeführt.

Bei der Ursachenforschung stellt sich mir die Frage: Was passiert wenn
die T3-Interrupt-Routine noch läuft und währenddessen T1 seinen
Overflow-Interrupt meldet?
Wird(sollte) die T1-Interrupt-Routine ausgeführt werden sobald
diejenige von T3 beendet ist?

Hat jemand einen Tipp für mich? Vielen Dank!

Autor: Peter M (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
so weit ich weiß sollte die T3 ISR beendet werden und dann die T1 ISR
ausgeführt werden.
Der T1 OVF hat eine "höhere Priorität" als der T3, unterbricht aber
die ISR vom T3 nicht, da der ATmega kein Prioritätensystem unterstützt.

Folglich sollte die T1-ISR nach der T3-ISR ausgeführt werden.

mfg Peter M.

Autor: Peter Pan IV (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, von dieser Reihenfolge bin ich auch ausgegangen.

So ein Mist, irgendwo hab ich mir da ein Bug reingestrickt.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Wie sieht denn der Code in den ISRs aus? Das hört sich fast so an, als
ob da irgendwelche komplizierten Sachen oder Wartezeiten drin sind?!?
Dann kann es natürlich passieren, dass ein oder mehrere Interrupts
geschlabbert werden. Wenn ein Interrupt-Ereignis eintritt und ein
anderes von der selben Quelle noch nicht bearbeitet ist, dann geht das
neue verloren.

Gruß

Johnny

Autor: Peter Pan IV (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier der Code für ISR von Timer1:

// Timer 1 overflow interrupt service routine, Sekundentakt
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
tp_time--;
if(tp_time == 0)
   {
   plot_calc_show(); // mit printf wird auf ein GLCD geschrieben
   }
TCNT1H=0x8F;   // Neuladen des Timers
TCNT1L=0x85;
}

Die T1-ISR wird ab und zu unterdrückt. Diese Unterdrückung geschiet im
Ganzzahligen Raster von Timer3, also alle 10sec, oder alle 50sec. In
plot_calc_show() wird die Länge eines senkrechten Striches berechnet
und mit printf, über RS232(9600 Baud) auf ein GLCD ausgegeben.

Die gesammte Verweildauer innerhalb der T1-ISR dürfte bei ca. 2msec
liegen, sie ist also kurz genug, bevor nach einer Sekunde der neue
Interrupt kommt.


Und hier der Code für Timer3

// Timer 3 overflow interrupt, alle ca. 10,1 Sekunden
interrupt [TIM3_OVF] void timer3_ovf_isr(void)
{
brighttime_count++;
if(brighttime_count == bt)
   {
   Timer3_AUS;
   Timer3_IE_AUS;
   brighttime_count = 0;
   brightm = 0;
   }
}


Ich arbeite nur mit dem AVR-JTAG. Ein Echtzeittrace ist damit ja nicht
möglich.

Peter P.

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"plot_calc_show(); // mit printf wird auf ein GLCD geschrieben "

Ob sowas wirklich in eine ISR gehört? Das bezweifle ich.

Autor: Peter Pan IV (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rahul, Deine Zweifel sind natürlich berechtigt. Normalerweise kommt
soetwas in die main.
Da ich die senkrechte Linie im GLCD aber Sekundengenau zeichnen
muss(Plot im 1-Sekundenraster), habe ich diese feste Anbindung an den
Sekundentakt gewählt.

In der main würden sich Zeitabweichungen von wenigen ms zu großen
Zeitfehlern aufaddieren.


Peter P.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> In der main würden sich Zeitabweichungen von wenigen ms zu großen
> Zeitfehlern aufaddieren.

Das glaube ich nicht.
In der ISR wird ein Flag gesetzt. In der Main wird dieses Flag geprüft
und falls es gesetzt ist, wird es gelöscht und der Job erledigt. Sollte
es Verzögerungen geben, weil die Main noch andere Arbeiten zu erledigen
hat, so kommt doch die nächste ISR pünktlich und setzt das Flag für die
nächste Ausgabe auch pünktlich. Es können sich also keine Verzögerungen
addieren.

...

Autor: Wolfram (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>// Timer 1 overflow interrupt service routine, Sekundentakt
>interrupt [TIM1_OVF] void timer1_ovf_isr(void)
>{
>tp_time--;
>if(tp_time == 0)
>   {
>   plot_calc_show(); // mit printf wird auf ein GLCD geschrieben
>   }
>TCNT1H=0x8F;   // Neuladen des Timers
>TCNT1L=0x85;
>}

>In der main würden sich Zeitabweichungen von wenigen ms zu großen
>Zeitfehlern aufaddieren.

wenn du mit deiner Overflowroutine wirklich einen Sekundentakt
generieren willst dann wirst du aber am Ende des Tages eine gewaltige
Abweichung haben.
Hast du schon mal in den erzeugten Assemblercode geschaut?
Dein Funktionsaufruf erzwingt das alle Register gesichert werden.
(Sind das nicht 32???)
ein printf aus einem Interrupt heraus finde ich sehr mutig.
(Ist printf eigentlich reentrant?)
der Zugriff auf ein LCD dürfte noch für zusätzliche verschiebung
sorgen.
Wenn du wirklich genau arbeiten willst dann nimm den Output Compare
Modus und setze ein Flag(volatile),dass du im Hauptprogramm pollst.
Ich denke das wird um einiges sekundengenauer.
Eine Interruptzeit sollte im unteren uSekundenbereich liegen!
BTW: was passiert eigentlich wenn tp_time <0 wird?

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"BTW: was passiert eigentlich wenn tp_time <0 wird?"
Das sollte am besten irgendwas "unsigned" sein, damit es zu einem
Überlauf kommt. Ob der richtig ausgwertet wird, ist fraglich, oder?

Autor: Peter Pan IV (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstmal danke für Eure Meinungen.

Werde versuchen die Grafikausgabe in der main zu steuern. Obwohl dort
schon ein externer ADC gepollt wird.


Vielen Dank!


Peter P.

Autor: Peter Pan IV (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, es klappt!

Eure Tipps, die Grafikroutine mit printf in die main zuverlegen war
Goldrichtig.
Und Zeitsynchron ist es auch.

Nochmals, vielen Dank!


Peter P.

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
*Muaahh!*

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Obwohl dort
> schon ein externer ADC gepollt wird.

ADCs pollt man nicht! Das kostet nur Rechenzeit, in der der Controller
Sinnvolleres tun könnte.

ADC fragt man entweder im ADC-Complete-Interrupt ab, oder in einem
Timer-Interrupt. Und wenn man mehrere Messquellen hat, dann schaltet
man sie nicht erst um, wenn man sie auslesen möchte, sondern
vorausschauen nach dem Auslesen der letzten Messquelle. Somit kostet
das Auslesen des ADCs absolut keine Wartezeiten.

Ich habe fast den Eindruck, dass ein Mega8 (Mega8535) mit 1MHz bei
vernünftiger Programmierung für deine Aufgaben voll reichen würde.

...

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.