Timerverhalten normal?

Gast #2588986
Hallo,

ich benutze den 16 Bit Timer meines Atmeag1284P um eine Zeitbasis für 
verschiedene Tasks zur Verfügung zu stellen.
(20Mhz, Prescaler 8)

Um die Dauer von einzelnen Programmabschnitten zu testen hab ich zwei 
kurze Funktionen geschrieben:
1
void TimerStart(uint16_t *temp)
2
{
3
  *temp = TCNT1;
4
}
5

6

7
void TimerStop(uint16_t *temp)
8
{
9
  *temp = TCNT1 - *temp;
10
}

Die Funktion ist selbsterklärend. In einer Variable wird die Differenz 
des Timerregisters gespeichert. Das könnte man jetzt noch in ms 
umrechnen, etc.

Benutze ich zum Testen folgenden Code (wird zyklisch ausgeführt)
1
Os_TimerStart(&time);
2
_delay_us(500);
3
Os_TimerStop(&time);

und lese dann die Variable aus (über USART am Terminal) sollte 
eigentlich mmer der gleiche Wert herauskommen. nur variiert dieser 
leicht. Das letzte Bit ist oft unterschiedlich.

Interrupt kann keiner hineinfunken da nur der Timerinterrupt läuft. 
Außerdem wäre der Unterschied dann ja wohl größer.

Hat jemand ne Idee was die CPU da so treibt?
Klar ist das LSB nicht wirklich wichtig. Soll ja nur ne grobe Schätzung 
sein wielang meine Funktionen ungefähr brauchen. Aber rein 
interessehalber wüsst ich schon gerne was da reinspielen kann..

Grüße,
lex
Gast
Ist das missverständlich ausgedrückt? Dann sorry :-)

Die Dauer, die ich testweise messe, sollte immer gleich lang sein, 
vorrausgesetzt _delay_us() wartet auch wirklich immer gleich lang.

Die einzige Möglichkeit, wieso diese Codeblock unterschiedlich lang 
dauern kann, ist das Auftreten eines Interrupts.
Und um diese mögliche Antwort von vornherein auszuschließen habe ich 
angemerkt, dass nur der Timerinterrupt aktiviert ist, sonst keiner.

Und dieser Ist erst kurz davor aufgetreten.

Außerdem würde ein Interrupt eine größere Schwankung der Dauer bewirken 
als nur das LSB.
Gast
Ohne den realen Code würde ich zu Deiner Frage keine Auskunft geben 
wollen.


Mir stellt sich die Frage warum Du überhaupt einen Interrupt an hast. 
Schalte den doch ab, dann ist auch der letzte Zweifel beseitigt, ob 
evtl. doch ein Int dazwischen haut.

Mit welchem Takt läuft denn der Timer?
lex schrieb:
> Hat jemand ne Idee was die CPU da so treibt?
Immer dasselbe. Solange bis der Strom abgeschaltet wird.

>(20Mhz, Prescaler 8)
Das ist ein Zähler. Der zählt von 0 bis 7 und bei 8 wird er wieder auf 0 
gesetzt und TCNT wird um 1 erhöht.
Angenommen du hast eine Funktion, die 100 CPU-Takte für die Abarbeitung 
braucht, dann zählt dein Timer in der Zeit 100/8 Timertakte = 12,5. Das 
kann er aber nicht, da er nur ganzzahlig zählen kann. Also 11, 12, 13.
Die Cpu-Takte sind dann 8, 16, ... 96, 104. 104, was der 13 entspräche, 
widr aber nicht mehr mitgezählt, weil er ja bei 100 schon fertig ist.

Bei zwölf ist deine Funktion also fertig und fragt den Wert ab.

Steht aber der Prescaler bei Beginn der Messung nicht auf 0 sondern auf 
4 oder größer, dann zählt TCNT bis 13. Nämlich 4, 12, 20... 92, 100. Und 
jetzt bekommt er die 100 mit und steht auf 13.

Und dann wackelt das niedrigste Bit.

mfg.
Gast
Dieser Interrupt generiert mir meine Zeitbasis, um z.B. zyklische den 
Wert per USART zu senden oder auf dem LCD auszugeben, ohne den läuft 
nichts.

Der Timer läuft wie gesagt mit 20Mhz / 8.
Das Compare Register steht auf 6249, macht ein Interrupt alle 2.5ms.
Gast
Ja, in der Tat wird der Überlauf nicht berücksichtigt.

Allerdings bewirkt ein Überlauf einen Taskwechsel. Sollte dieser wärend 
einer Zeitmessung auftreten bedeutet das, der vorherige Task ist nicht 
abgeschlossen.

Und dann is eh alles zu spät, dann schlägt nämlich ein ErrorHook zu. Ein 
Task darf nicht länger als 2.5ms dauern.

Bastl grad ein simples Zeitscheiben OS zur Übung.

Grüße,
lex

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.