Timer Interrupt funktioniert nicht

Gast #1710073
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
Angehängte Dateien:
Gast #1710094
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
#1710103
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
Gast #1710127
Lesenswert?

Danke für die Antworten.

ich habe das Programm folgender masen verändert:
1
   TCCR0 &= ~(1<<CS02)|(1<<CS01);  // Kein Prescaler 
2
   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?
#1710152
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.
Gast #1710164
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.
Gast #1710861
Lesenswert?

Hallo,

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

7
ISR(TIMER0_COMP_vect)
8
{
9
    timer ++;
10
}
11

12
//Hauptprogram
13

14
int main(void)
15
{
16
  //Ein - Ausgänge Definieren
17

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

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

24

25
  // Timer 0 konfigurieren
26

27
  //Prescalerkonfiguration
28
    TCCR0 &= ~(1<<CS02)|(1<<CS01);  // Kein Prescaler 
29
    TCCR0 |= (1<<CS00);        //    "
30
  
31
  //CTC Modus aktivieren
32
  TCCR0 &= ~(1<<WGM00);
33
  TCCR0 |= (1<<WGM01);
34

35
  //Output Compare Interrupt erlauben
36
  TIMSK |= (1<<OCIE0);
37
  
38
  /*Output Compare Register vorladen mit 40
39
    Interrupt Aktion alle (4000000/40 = 1000.000Hz = 10µs
40
    ausführen
41
  */
42
  OCR0 = 0x19;
43
  
44
  //Interupt starten
45
  sei();
46

47

48

49
  while(1)
50
  {
51
      LED = 0x00;
52
      wartems(250);
53
      wartems(250);
54
      wartems(250);
55
      wartems(250);
56
      LED = 0xff;
57
      wartems(250);
58
      wartems(250);
59
      wartems(250);
60
      wartems(250);
61
  }
62

63
}


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?
#1710885
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.
Gast #1710918
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.
#1710964
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.
#1711099
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren