www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer Interrupt funktioniert nicht


Autor: Jürgen (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich versuche gerade einen ganz einfachen Timer zu programmieren.
Ausrüstung:
Atmega 8515, 4Mhz Quarz, AVR-Studio, GCC.

Es will einfach nicht funktionieren.
Ich kann mit dem AVR Studio ja schön simulieren und habe festgestellt, 
dass die 100 an die Funktion wartems nicht weitergegeben wird. Siehe 
Bild1.jpg.

Mir ist der Verdacht aufgekommen, dass eventuell der Simulator Bugs hat 
und habe das Programm auf den Controller gespielt. Funktioniert aber 
auch nicht.

Habe ich irgend wo was vergessen?

Jürgen

PS: timer.c ist das Hauptprogramm

Autor: Joachim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Schau dir mal warteus an. Kommst du da jemals wieder raus.
timer bleibt immer 0 und somit immer kleiner timerus (falls > 0)

Warum werden solche wartezeiten eigentlich immer neu erfunden??

Gruß
Joachim

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

Bewertung
0 lesenswert
nicht lesenswert
Joachim schrieb:
> Hallo
>
> Schau dir mal warteus an. Kommst du da jemals wieder raus.
> timer bleibt immer 0 und somit immer kleiner timerus (falls > 0)

Das ist nicht der Grund.
timer ist eine globale Variable, die in der ISR erhöht wird.

>     TCCR0 &= ~(1<<CS01)|(1<<CS00);  // Kein Prescaler

Ein Timer läuft, sobald du einen Prescaler zuweist.
Hat der Timer einen Prescaler von 0, so läuft er auch nicht. Ein Timer 
der nicht läuft, zählt auch nicht. Ein Timer der nicht zählt generiert 
auch keine Overflows. Keine Overflows, keine ISR. Den Rest kannst du dir 
denken

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Antworten.

ich habe das Programm folgender masen verändert:
   TCCR0 &= ~(1<<CS02)|(1<<CS01);  // Kein Prescaler 
   TCCR0 |= (1<<CS00);

Jetzt funktionierts zwar auf dem Controler aber die Simulation stimmt 
immer noch nicht. Auserdem stimmt die Wartezeit nicht. Eine Periode 
(Also LED an, LED aus) dauert 1.86s. Deshalb wollte ich ja eine eigene 
Routine machen um eine genaue Zeit zu bekommen.
Wo habe ich falsch gedacht?

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

Bewertung
0 lesenswert
nicht lesenswert
Jürgen schrieb:

> Wo habe ich falsch gedacht?

µC sind zwar schnell. Aber so schnell auch wieder nicht. Du gibst dem 
Timer genau 4 Taktzyklen Zeit ehe er den nächsten Overflow auslösen 
soll. 4 Takte, da ist der Inhalt deiner ISR schon länger.

Kurz gesagt: Deine Vorgaben sind nicht erfüllbar.

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohh, da übervordere ich ihn ein bischen. :-)

muss ich woll ein wennig umrechnen.

Aber wieso funktioniert es in der Simulation nicht?

Danke.

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich den Timer mit 216 vorlade, dauert es 10µs bis der nächste 
Interrupt kommt. Ist das besser?

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

Bewertung
0 lesenswert
nicht lesenswert
Au´s dem Bauch heraus: 40 Takte ist immer noch verdammt wenig.

Und gewöhn dir den Quatsch mit Vorladen am besten gleich wieder ab, wenn 
du halbwegs vernünftige Timings haben willst (zumindest bei einem 
Vorteiler von 1). Vom Zeitpunkt wenn der Timer seinen Overflow auslöst, 
bis er sich zum ISR Aufruf bequemt, bis du in der ISR die Kontrolle 
kriegst ... da vergeht alles Zeit. Zeit in der der Timer in der 
Zwischenzeit weitergezählt hat. Zähltakte die du aber nirgends 
berücksichtigt. Wenn man eine Timer-ISR braucht, die abweichend von der 
Breite des Timers (8Bit oder 16 Bit) aufgerufen wird, dann nimmt man den 
CTC-Modus des Timers dafür.

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, CTC-Modus, interessant. Wir in der Schule haben immer nur den 
einen Timer verwendet. CTC-Modus werde ich mir morgen mal anschauen.

Fühle mich bei euch gut aufgehoben.

Gute Nacht und nochmals Danke.

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

Bewertung
0 lesenswert
nicht lesenswert
Jürgen schrieb:
> Danke, CTC-Modus, interessant. Wir in der Schule haben immer nur den
> einen Timer verwendet. CTC-Modus werde ich mir morgen mal anschauen.

http://www.mikrocontroller.net/articles/AVR-Tutorial:_Uhr

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

hab mich jetzt ein wennig reingelesen.
Jetzt funktioniert´s auch. Aber ich weis nicht warum. :-)
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "warten.h"
#include "var.h"

ISR(TIMER0_COMP_vect)
{
    timer ++;
}

//Hauptprogram

int main(void)
{
  //Ein - Ausgänge Definieren

  DDRC  = 0xff;    //PORTC Ausgang (LEDs)
  PORTA = 0xff;    //PORTA Pullup aktivieren (Taster)

  DDRD  = 0xff;    //PORTD (Display Daten) auf Ausgang setzten
  DDRB  =  0x07; // Asugänge schalten für Display RS/RW/E


  // Timer 0 konfigurieren

  //Prescalerkonfiguration
    TCCR0 &= ~(1<<CS02)|(1<<CS01);  // Kein Prescaler 
    TCCR0 |= (1<<CS00);        //    "
  
  //CTC Modus aktivieren
  TCCR0 &= ~(1<<WGM00);
  TCCR0 |= (1<<WGM01);

  //Output Compare Interrupt erlauben
  TIMSK |= (1<<OCIE0);
  
  /*Output Compare Register vorladen mit 40
    Interrupt Aktion alle (4000000/40 = 1000.000Hz = 10µs
    ausführen
  */
  OCR0 = 0x19;
  
  //Interupt starten
  sei();



  while(1)
  {
      LED = 0x00;
      wartems(250);
      wartems(250);
      wartems(250);
      wartems(250);
      LED = 0xff;
      wartems(250);
      wartems(250);
      wartems(250);
      wartems(250);
  }

}


Durch rumprobieren habe ich herausgefunden das ich das Register OCR0 mit 
HEX 19 also DEZ 25 beschreiben muss um auf die z.B. 1s zu kommen.
Dass würde aber nicht meiner Rechnung entsprechen die folgendermaßen 
aussieht: 4.000.000/40 = 100.000 Hz = 10µs.

Mit HEX 19 sieht es aber so aus: 4.000.000/25 = 160.000 Hz = 6,25µs.

Wie kommt das?

Außerdem habe ich nicht ganz verstanden wo der Unterschied zwischen den 
beiden Modusen ist. Ich muss doch beide Vorladen.

Auch das simulieren funktioniert nicht. Es kommt immer noch die 
Meldung:"Location not valid"

Wo mache ich Fehler?

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

Bewertung
0 lesenswert
nicht lesenswert
25 Takte von einem Interrupt zum nächsten ist immer noch sehr eng.
Lass doch dem µC etwas Zeit!

Deine 4Mhz, wo kommen die her?
interner Oszillator, Quarz?

> Außerdem habe ich nicht ganz verstanden wo der Unterschied zwischen
> den beiden Modusen ist. Ich muss doch beide Vorladen.

Im CTC lädst du in der ISR den Timer nicht vor.
Der Timer zählt von sich aus nur bis zu einer bestimmten Zahl


> Es kommt immer noch die
> Meldung:"Location not valid"

Du hast den Optimizer eingeschaltet und der Optimizer hat die Variable 
rausgeworfen, weil er sie nicht braucht.

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Lass doch dem µC etwas Zeit!

Am Anfang wollte ich eine Routine schreiben um eine Funktion zu haben 
Portionsweise 1 µs hochzuzählen.
Jetzt muss ich die Portionen schon erhöhen um 10. Das muss dem doch 
reichen!! :-)

Aber im ernst, wie kann ichs besser machen. Und komm mir ja nicht mit 
_delay ... . ;-) Genau das möchte ich umgehen. Ich habe gelesen, sobald 
ein Interrupt dazwischen kommt, stimmt die Zeit nicht mehr. Deshalb 
wollte ich was eigenes machen.
Und da ich die Timer sowieso besser kennen lernen wollte habe ich es als 
Übung versucht.

Karl heinz Buchegger schrieb:
> Deine 4Mhz, wo kommen die her?
> interner Oszillator, Quarz?

externem Quarz.

Karl heinz Buchegger schrieb:
> Im CTC lädst du in der ISR den Timer nicht vor.
> Der Timer zählt von sich aus nur bis zu einer bestimmten Zahl

Verstanden. Danke.

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

Bewertung
0 lesenswert
nicht lesenswert
Jürgen schrieb:

> Jetzt muss ich die Portionen schon erhöhen um 10. Das muss dem doch
> reichen!! :-)

Wenn du im Büro sitzt und alle 15 Sekunden kommt wer rein und will was 
von dir, kriegst du auch deine eigentliche Arbeit nicht mehr auf die 
Reihe.

Beschränkst du aber den Zugang zu dir auf alle 5 Minuten, dann geht auch 
bei dir was weiter.

>> Deine 4Mhz, wo kommen die her?
>> interner Oszillator, Quarz?
>
> externem Quarz.

ok.
Das erklärt dann nicht den zeitlichen Versatz

>> Im CTC lädst du in der ISR den Timer nicht vor.
>> Der Timer zählt von sich aus nur bis zu einer bestimmten Zahl
>
> Verstanden. Danke.

Der springende Punkt ist:
Der Timer zählt von sich aus exakt die angegebene Anzahl an Takten ab. 
Beim vorladen hast du immer einen Versatz drinnen, durch Dinge die du 
nicht beeinflussen kannst.

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das heist ich muss mir die 10µs abschmincken?

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

Bewertung
0 lesenswert
nicht lesenswert
Jürgen schrieb:

> Aber im ernst, wie kann ichs besser machen. Und komm mir ja nicht mit
> _delay ... . ;-) Genau das möchte ich umgehen.

Das kann man so pauschal nicht sagen.
Das hängt natürlich auch immer von der Taktfrequenz ab.
Bis zu einer gewissen Grenze sind _delay... schon in Ordnung. Vor allen 
Dingen, weil du das auch mit einem Timer nicht genauer hinkriegst, ganz 
im Gegenteil.

> Ich habe gelesen, sobald
> ein Interrupt dazwischen kommt, stimmt die Zeit nicht mehr.

Vor den _delay.. einfach die Interrupts deaktivieren und danach wieder 
einschalten.


Ich würde mal aus dem Bauch heraus sagen:
Bis zu ~500µs sind _delay... durchaus verschmerzbar, wenn es nicht im 
Programm andere Gründe gibt, warum man auf keinen fall warten möchte.

Denn: Auch ein Timer ist kein Allheilmittel. Vor allen bei kleinen 
Zeiten wirds mit einem Timer schin knifflig.

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Vor allen bei kleinen
> Zeiten wirds mit einem Timer schin knifflig.

Das habe ich jetzt auch gemerkt.

Okay, habs jetzt soweit verstanden.

Herzlichen Dank für deine Mühe.

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.