Forum: Mikrocontroller und Digitale Elektronik Timer0 Mega32 10Khz erzeugen


von Dilligent (Gast)


Lesenswert?

Hallo alle, ich bin irgendwie ein bisschen verwirrt, ich fahre einen 
Mega32 mit 2Mhz und möchte einen Timer verwenden der einen Interrupt in 
0.1ms intervallen aufruft. Nun meine "Rechnungen":

2.000.000 = 1sec
      200 = 0.1msec

0.1msec entsprechen 10 Khz. folglich muss ich eine 10KHz taktung 
erzeugen.

in 1 sec vergehen 2.000.000 takte, in 0.1msec folglich also 200.
Nun nehme ich mir den 8Bit timer0 vom mega32 im überlauf modus und setze 
das TCNT0 auf 56 (damit es nach 200 takten überläuft und meine routine 
aufruft).


#define CLK_RATE  10000
#define CNT    256 - (XTAL / CLK_RATE)

void init_int_timer()
{

  TCCR0 |= 1 << CS00;
  TCNT0 = CNT;
  TIMSK |= (1<<TOIE0);

  sei();
}

ISR(TIMER0_OVF_vect)
{
  static short i = 0;

  TCNT0 = CNT;

  i++;

  if(i == 10000)
  {
    add_time(&dset.timeofday, 1);
  }
}

Ich schreib das alles so ausführlich weil es nicht richtig funktioniert, 
das intervall ist zu groß, ich habs mal im Simulator durchgespielt und 
gesehen das da immer exakt 241 Takte statt 200 vergehen.

Wie kann das sein, wo ist mein Fehler?

Danke im vorraus, Dennis

von Andreas K. (a-k)


Lesenswert?

Womit wird der Mega32 getaktet?
Hat dieser Timer einen CTC-Modus?

von Dilligent (Gast)


Lesenswert?

Der mega32 wir mit internem 2Mhz Oszilator getaktet, sitzt auf nem 
STK500, soweit ich weiss haben nur die 16bit timer CTC

von Andreas K. (a-k)


Lesenswert?

Hmm, irgendwas ist hier schräg. Einerseits STK500, andererseits lese ich 
grad "Simulator". Wenns echte Hardware ist, hätte ich auf unkalibrierten 
RC-Oszillator getippt. Beim Simulator geht das schlecht.

von Johannes M. (johnny-m)


Lesenswert?

Timer 0 hat CTC. Beim Mega8 hatte er es noch nicht. Ab ATMega16 haben 
auch die 8-Bit-Timer PWM und CTC.

von Dilligent (Gast)


Lesenswert?

Simulator: Hab das im AVR-Studio simuliert nachdem's aufm STK500 halt zu 
langam lief und da werden mir halt auch die akutelle taktzahl und 
weiteres ausgegeben...

Ich verstehe immer noch nicht wirklich warum das Problem überhaupt 
besteht

von crazy horse (Gast)


Lesenswert?

und ansonsten musst du natürlich die Anzahl der Takte berücksichtigen, 
die vergehen, bevor TCNT nachgeladen wird. Konmmt einerseits auf dein 
Programm (steht richtig an 1.Stelle), allerdings baut dir der Compiler 
etliches ein, was du nicht direkt siehst (Sicherung diverser Sachen). 
Das kann man berücksichtigen, ist allerdings bei einem 
Compilerupdate/anderen Optimierungseinstellungen und auch schon bei 
simplen Sourcecode-Änderungen schon wieder ein anderer Wert.
CTC-mode ist genau das richtige für sowas.

von Johannes M. (johnny-m)


Lesenswert?

Dilligent wrote:
> Ich verstehe immer noch nicht wirklich warum das Problem überhaupt
> besteht
Erstmal hat die ISR ne Menge Overhead. 40 Takte sind da zumindest nicht 
ganz abwegig, immerhin machst Du in der ISR 16-Bit-Operationen. Also 
mach es mit CTC, dann sollte es präzise klappen. Hast Du die 
Compiler-Optimierung eingeschaltet? Wenn nicht, dann machen.

von Andreas K. (a-k)


Lesenswert?

Ein paar Takte gehen aufgrund des fehlenden CTC-Modus drauf, das ist 
klar, denn die Reaktionszeit des Interrupt-Handlers geht so voll ins 
Timing ein. 41 Takte erscheinen mir dafür aber etwas viel.

von Andreas K. (a-k)


Lesenswert?

Johannes M. wrote:

> ganz abwegig, immerhin machst Du in der ISR 16-Bit-Operationen.

Aber erst nach dem entscheidenen Reload vom TCNT0.

von Johannes M. (johnny-m)


Lesenswert?

Andreas Kaiser wrote:
>> ganz abwegig, immerhin machst Du in der ISR 16-Bit-Operationen.
>
> Aber erst nach dem entscheidenen Reload vom TCNT0.
Richtig. Aber bei bestimmten Operationen in der ISR werden u.U. mehr 
Register gesichert, als wenn man nur 8-Bit-Fummeleien macht.

von crazy horse (Gast)


Lesenswert?

hat trotzdem Einfluss darauf, wieviel der Compiler sichert.

von Dilligent (Gast)


Lesenswert?

Möchte mich bei allen ganz herzlich bedanken, hab im datenblatt nochma 
nachgeschaut, natürlich hzat der 8Bit timer CTC..

Gut, da ich aber sowieso gerne mal die Taktfrequenz anheben wollte hab 
ich mich entschieden nun doch einen 16Bit timer zu nehemn und habs nun 
am laufen.
Es scheint auch alles wunderbar zu funktionieren :)

#define CLK_RATE  10000
#define CNT      XTAL / CLK_RATE

void init_int_timer()
{
  /* CTC1 enabled, CLK source */
  TCCR1B |= (1<<WGM12) | (1<<CS10);

  /* Set Counter to 0 */
  TCNT1  = 0;

  /* Interrupt on compare match */
  TIMSK |= (1 << OCF1A);
  OCR1A  = CNT - 1;
}

ISR(TIMER1_COMPA_vect)
{
  static short i = 0;
  i++;

  if(i == 10000)
  {
    add_time(&dset.timeofday, 1);
    i = 0;
  }
}

Funktioniert wunderbar, (CNT - 1) macht aus irgendeinem Grunde den Timer 
viel genauer da sonst aus irgendeinem Grunde immer 200 - 202 takte 
gemacht wurden. Nun gleicht sich das immer wieder von selbst aus, 
vertsehe ich nicht, funktioniert aber. Wunderbar, dann hab ich ja jetzt 
einen guten Zeitbezug ;)

Schöne Grüße, Dennis

von Johannes M. (johnny-m)


Lesenswert?

Dilligent wrote:
> Funktioniert wunderbar, (CNT - 1) macht aus irgendeinem Grunde den Timer
> viel genauer da sonst aus irgendeinem Grunde immer 200 - 202 takte
> gemacht wurden.
201 Takte vermute ich mal... Schließlich wird das Compare-Flag erst im 
der Gleichheit der Werte folgenden Takt gesetzt. Wenn Du nach 200 Takten 
den Timer zurückgesetzt haben willst, muss im Compare-Register 199 
stehen.

von Karl H. (kbuchegg)


Lesenswert?

Und da du jetzt den Timer 1 benutzt, macht es auch Sinn
den OCR Wert auf 1999 hoch zu setzen und dafür nur auf
1000 Interrupts zu warten.
Alternativ: den OCR Wert auf 19999 und nur 100 Interrupts.
Oder 39999 und 50 Interrupts.

Insebsondere die letzten beiden Kombinationen ermöglichen
dann, dass dein i in der ISR nur noch ein uint8_t sein
muss, was die ISR wiederrum von 16 Bit Arithmetik (zumindest
für das i) befreit.

Je weniger Interrupts, desto mehr Zeit hat dein µC um
dazwischen noch Däumchen zu drehen :-)

von Dilligent (Gast)


Lesenswert?

Die unschöne 16Bit Arithmetik mag ich auch nicht so unbedingt, leider 
hab ich aber Signale deren Länge ich mit 0.1msec auflösung auslesen 
müsste :/

Bleibt mir leider nicht viel übrig, übrigens geht die Uhr ziehmlich vor, 
7sec  nach 4 minuten, hab daraufhin mal das #define XTAL angepasst, is 
schon echt viel, (bei 8Mhz jetzt)

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.