Forum: Mikrocontroller und Digitale Elektronik 1 Millisekunden Takt mit ARV 90S8535


von Stephan (Gast)


Lesenswert?

Hallo,

ich mache gerade meinen ersten Schritte in der AVR Welt.
Ich benötige für mein Projekt einen 1 Millisekunden Takt in Verbindung
mit eine Countdown Timer.

Nun meine Frage:
Mein Board hat einen 8 MHz Quarz und einen Uhrenquarz 32768 Hz.

Wie komme ich am besten auf einen 1 ms Impuls z.B. Interrupt.

Vielen Dank im voraus.

Stephan

von Santa Klaus (Gast)


Lesenswert?

Das kannst Du z. B. erreichen, indem Du den Timer 1 im CTC-Mode ("CTC"
= "clear on timer compare") ohne Vorteiler laufen läßt und den
Compare-Wert auf 8000 setzt (oder mit Vorteiler 8 und Compare-Wert 1000
etc.).

Bei jedem Erreichen des Compare-Werts stellt sich der T/C1-Zähler
automatisch auf Null zurück und ein "T/C1 compare match A"-Interrupt
wird ausgelöst (vorausgesetzt Du hast ihn enabled).  Somit wird dieser
Interrupt alle 1 ms getriggert.

Möchtest Du die Frequenz lieber von dem Uhrenquarz ableiten, kannst Du
das auf ähnliche Weise bewerkstelligen.

Details findest Du im Data Sheet des Controllers Deiner Wahl.

von Peter D. (peda)


Lesenswert?

@Santa Klaus,


würde mich ja schon sehr interessieren, wie Du 32768 durch 1000 ohne
Rest teilen wilst.


Peter

von Stephan (Gast)


Lesenswert?

Hallo,

hat einen ein Stück Programmcode für mich. Wie kann ich das mit WinAVR

umsetzen.

Schon mal vielen Dank

Gruß

Stephan

von Santa Klaus (Gast)


Lesenswert?

>wie Du 32768 durch 1000 ohne Rest teilen wilst.

@Peter & Stefan:

Man kann zwar 32768 nicht ohne Rest durch 1000 teilen, aber man kann
trotzdem aus einem 32768-Takt einen 1 ms-Takt gewinnen.

Bei einem Compare-Wert von 8 produziert der Uhrenquarz-Timer Interrupts
mit der Frequenz 32768/8 Hz = 4096 Hz.  Mit dieser Frequenz den µC eine
(sehr kleine) Rechnung durchführen zu lassen, sollte OK sein.

Ein softwaremäßige Frequenzteilung durch 4 nach diesem Schema

---------------------------------
Interrupt:

inc(Count);

IF (Count==4)
  {
  Count=0;
  OneMillisecondHandler;
  }

reti
---------------------------------

würde auf die Frequenz 1024 Hz führen.  Das ist etwas zu viel, bzw. die
"OneMillisecondHandler"-Aufruftakte wären etwas zu klein (1/1024 s =
0.9765625 ms statt der gewünschten 1 ms).

Man kann nicht erreichen, daß jeder Takt genau 1 ms lang ist (weil
32768 ist nicht ohne Rest durch 1000 teilbar ist), aber machbar ist
eine Taktlänge von 1 ms im zeitlichen Mittel (!).

Dazu ist es notwendig, den Grenzwert des Software-Teilers variabel zu
machen.  Wir lassen die Variable Count nicht in allen Fällen bis 4
zählen, sondern ab und zu auch mal bis 5 (!).  Die Idee ist, die etwas
zu kurzen 4er-Takte durch eine genau passende Anzahl etwas zu langer
5er-Takte auszugleichen.  Wie groß diese "passende Anzahl" ist,
rechnen wir aus:

 (N*4 + n*5) * (1/4096) s
-------------------------- = 1 ms
          N + n

Die linke Seite ist das zeitliche Mittel des Zeittaktes, den wir im
Durchschnitt erhalten, wenn wir die Variable "Count" N mal bis 4, und
n mal bis 5 zählen lassen.

Das liefert:

N * 4 + n * 5 = (N + n) * 4096/1000

4000 N + 5000 n = 4096 N + 4096 n

904 n = 96 N

n = 96/904 N

n = 12/113 N    (12/113 ist nicht mehr weiter kürzbar)

Damit wissen wir, daß auf je 113 4er-Takte genau 12 5er-Takte kommen
müssen, damit die Sache stimmt (wer's nicht glaubt, mache unverzüglich
die Probe...).

Der Interrupt-Handler müssen wir wie folgt gestalten:

---------------------------------
Interrupt:

IF (M>=12) CountMax=4 ELSE CountMax=5;

inc(Count);
IF (Count==CountMax)
  {
  Count=0;
  OneMillisecondHandler;
  }

inc(M);
IF (M==113+12) M=0;

reti
---------------------------------

Die Routine "OneMillisecondHandler" wird jetzt 90.4% einer Sekunde
mit einem Takt von 0.9765625 ms ausgeführt, und in den restlichen 9.6%
mit einem Takt von 1.2207 ms.  "Zusammen" resultiert daraus ein
mittlerer Takt von genau 1 ms.

Wer sich nicht scheut, kann statt eine "Count"-Variable zu verwenden,
dieses Prinzip auch direkt mit dem Compare-Match-Register des
Hardware-Timers realisieren.  Ohne die "M"-Variable geht es
allerdings nicht.

Ich hoffe, das war verständlich.

von Santa Klaus (Gast)


Lesenswert?

Achtung, Korrektur:

Der vermaledeite Interrupt-Handler muss natürlich so aussehen:

---------------------------------
Interrupt:

inc(Count);
IF (Count==CountMax)
  {
  Count=0;
  OneMillisecondHandler;

  inc(M);
  IF (M==113+12) M=0;

  IF (M>=12) CountMax=4 ELSE CountMax=5;
  }

reti
---------------------------------

von Werner Hoch (Gast)


Lesenswert?

@ Santa Klaus:
Wozu der Aufwand?
Der OP hat einen 8MHz Takt, der ist natürlich durch 8000 teilbar.

von Santa Klaus (Gast)


Lesenswert?

@Werner Hoch:

Wenn man die Frequenz aus dem Uhrenquarz ableitet, kann man "tiefe"
Sleepmodes (Anhalten des 8 MHz-Systemtaktes) nutzen und so ein Maximum
an Strom sparen. Außerdem sind Uhrenquarze bzgl. Abgleichtoleranz und
Temperaturdrift besser als Systemtakt-Quarze.

von Werner Hoch (Gast)


Lesenswert?

der OP wollte einen Millisekundentakt. Für die Langzeitstabilität ist
der Uhrenquarz natürlich besser, da stimme ich dir zu.
Ansonsten gilt:
8000000/8000 = 1ms
32768/ 1000 = autsch

von Andi (Gast)


Lesenswert?

Es gibt doch auch 32,000KHz Quarze was das ganze sehr vereinfachen
würde. Müsste doch auch an T2 laufen.
Oder sind die nicht so genau wie 32,768KHz?

Gruß
Andi

von Peter D. (peda)


Lesenswert?

Prinzipbedingt sind Quarze im MHz-Bereich temperaturstabiler und haben
auch eine höhere Güte.
Man erreicht damit also eine wesentlich höhere Konstanz als mit
Uhrenquarzen.

Allerdings sind billige µC-Quarze nicht so genau abgeglichen, d.h. man
muß sie erstmal abgleichen.
Ausnahmen sind spezielle Referenzquarze (1MHz, 10MHz), die kosten aber
auch mehr.

Um nun mit Uhrenqurzen die gleiche Temperaturstabilität zu erreichen
muß man spezielle Tricks anwenden.
Von Maxim gibt es z.B. eine 32kHz-Referenz, in der die Temperatur
gemessen wird und damit dann die Frequenz korrigiert wird.


Peter

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.