Forum: Mikrocontroller und Digitale Elektronik Timerverhalten normal?


von lex (Gast)


Lesenswert?

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

von Timer (Gast)


Lesenswert?

lex schrieb:
> Interrupt kann keiner hineinfunken da nur der Timerinterrupt läuft.

Wie bitte ?

von lex (Gast)


Lesenswert?

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.

von Noname (Gast)


Lesenswert?

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?

von Thomas E. (thomase)


Lesenswert?

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.

von lex (Gast)


Lesenswert?

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.

von lex (Gast)


Lesenswert?

Danke Thomas Eckmann, sehr schön erklärt. Da war mir wohl die genaue 
Arbeitsweise des Prescalers nicht klar.

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Du hast nirgendwo nen Ueberlauf beruecksichtigt... funktioniert so 
nicht. Zuruecksetzen des TCNT-Registers kann auch helfen wenn Du sicher 
sein kannst dass in der gegebenen Zeit kein Ueberlauf stattfindet, 
ansonsten den Ueberlauf-Interrupt verwenden.

von Thomas E. (thomase)


Lesenswert?

Im "GTCCR – General Timer/Counter Control Register" kann man den 
Prescaler zurück setzen.

mfg.

von lex (Gast)


Lesenswert?

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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.