www.mikrocontroller.net

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


Autor: Stephan (Gast)
Datum:

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

Autor: Santa Klaus (Gast)
Datum:

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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Santa Klaus,


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


Peter

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

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

umsetzen.

Schon mal vielen Dank

Gruß

Stephan

Autor: Santa Klaus (Gast)
Datum:

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

Autor: Santa Klaus (Gast)
Datum:

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

Autor: Werner Hoch (Gast)
Datum:

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

Autor: Santa Klaus (Gast)
Datum:

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

Autor: Werner Hoch (Gast)
Datum:

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

Autor: Andi (Gast)
Datum:

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

Autor: Peter Dannegger (peda)
Datum:

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

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.