www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer0 Mega32 10Khz erzeugen


Autor: Dilligent (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Womit wird der Mega32 getaktet?
Hat dieser Timer einen CTC-Modus?

Autor: Dilligent (Gast)
Datum:

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

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Johannes M. (johnny-m)
Datum:

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

Autor: Dilligent (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johannes M. wrote:

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

Aber erst nach dem entscheidenen Reload vom TCNT0.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hat trotzdem Einfluss darauf, wieviel der Compiler sichert.

Autor: Dilligent (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

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

Bewertung
0 lesenswert
nicht 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 :-)

Autor: Dilligent (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)

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.