Forum: Mikrocontroller und Digitale Elektronik 1 second time-base peter dannegger


von Mark (Gast)


Lesenswert?

Hallo!

Ich habe mir nun einmal den Code von peter Dannegger angeschaut,
welcher eine präzise 1-Sekunden Zeitbasis darstellt.

Nur habe ich dazu einige Fragen:

1.)Der Codeabschnitt:


#define XTAL    11059008L  // after measuring deviation: 1.5s/d

#define DEBOUNCE  256L

#if XTAL % DEBOUNCE
                // compare (DEBOUNCE - 1) times
      OCR1A = XTAL / DEBOUNCE - 1;
#endif

Da verstehe ich folgendes nicht ganz. "%" an sich ist ja eine Modulo
Operator.

Das beudeutet der Ausdruck "XTAL % DEBOUNCE" ist ungleich Null,
sofern bei der Division von XTAL durch DEBOUNCE ein Rest bleibt,
richtig? (und das wird immer der Fall sein, es sei denn XTAL und
DEBOUNCE sind gleich groß)

SO...nun zu den Fragen:
1.)Wieso überhaupt diese Division, oder anders gefragt, wozu ist dieser
Prescaler gut?

2.)Was genau macht die Zeile:

OCR1A = XTAL / DEBOUNCE - 1;    // compare (DEBOUNCE - 1) times

Also warum wird (DEBOUNCE - 1)  mal verglichen? Und was wird
verglichen?

Falls jemand so freundlich sein könnte , mir auf die Sprünge zu
helfen,ich seh da absolut nicht durch ;-)

von Mark (Gast)


Lesenswert?

P.S.:

Ich nehme an, der prescaler von 256 hat etwas damit zu tun, dass das
Timerregister ein 8 Bit Register( von 0- 255) ist?!

von Rahul (Gast)


Lesenswert?

1. Hast du mal für ein paar Werte die Division ausgerechnet?
Der Prescaler ist auf die Genauigkeit bezogen. Darauf geht Peter in
mehrern Threads ein.
Übrigens ändert sich die 256 eher selten. Die Quarzfrequnez ändert
sich.
(Der Rest einer Divison ist immer dann gleich Null, wenn der Dividend
ein ganzes Vielfaches des Divisors ist: 10 % 5 = 0, 20 % 5 = 0, 21 % 5
= 1...

von Rahul (Gast)


Lesenswert?

2. die -1 kommt vom CTC-Modus des Timers: Der Timer braucht einen
Taktzyklus, um modifiziert zu werden.

von Mark (Gast)


Lesenswert?

Ja ok, aber die ganze ISR sieht ja so aus:

SIGNAL (TIMER1_COMPA_vect)
{

  #if XTAL % DEBOUNCE
      OCR1A = XTAL / DEBOUNCE - 1;
  #endif

    if( --prescaler == 0 )
    {
        prescaler = (uchar)DEBOUNCE;
        second++;    // exact one second over

  #if XTAL % DEBOUNCE
       OCR1A = XTAL / DEBOUNCE + XTAL % DEBOUNCE - 1;
  #endif
    }
}

Machdem der Rest ja Präprozessor Anweisungen sind, besteht das
eigentlich "Programm" aus dem Code

if( --prescaler == 0 )
    {
        prescaler = (uchar)DEBOUNCE;
        second++;    // exact one second over
        }

Das Hauptprogramm startet bei einem Timerwert von 0, zählt dann rauf
bis zu
OCR1A = XTAL / DEBOUNCE - 1;

Dann wird in die ISR gesprungen, der prescaler um 1 dekrementiert und
geprüft, ob dieser bereits 0 ist. Dann ist eine Sekunde vergangen, weil
ja schon 256 mal der COMPARE MATCH ausgelöst wurde...

Nur, das XTAL / DEBOUNCE -1 beschäftigt mich trotzdem...
Dass der Timer einen Takt zum modifizieren braucht leuchtete ein, nur
durch das "-1" bewirkt doch lediglich, dass dieser Takt "nicht
mitgezählt" wird.... Aber die Zeit ist ja trotzdem verstrichen....?!!

von peter dannegger (Gast)


Lesenswert?

Wenn Du durch 3 teilen willst, zählt der Timer 0, 1, 2, 0 usw., d.h. Du
mußt mit 2 vergleichen, damit danach wieder die 0 kommt, und 2=3-1.


Peter

von Mark (Gast)


Lesenswert?

Mhm, ok.

Stimmt es dann also, dass ich den Prescaler "DEBOUNCE" frei wählen
kann?

Ich stelle mir das nun so vor:

Je kleiner der DEBOUNCE Wert --> desto größer ist der Wert, der ins
Register OCR1A geladen wird --> es passiert weniger of ein Compare
Match --> Weniger ISR Aufrufe.
Dafür wird aber auch schon nach einer geringeren Anzahl von Interrupts
die Sekunde weitergezählt.

Im Endeffekt sollte aufgrund der zusätzlichen Korrektur mit

OCR1A = XTAL / DEBOUNCE + XTAL % DEBOUNCE - 1;

also DEBOUNCE jeden beliebigen Wert annehmen können.

Ein DEBOUNCE Wert von 256 wurde also lediglich gewählt, um mit den 4ms
nebenbei eine praktische Zeitbasis für eine Tastenentprellroutine zu
haben?

Ist das so richtig?

von Mark (Gast)


Lesenswert?

Mit anderen Worten:

Das "-1" im Ausdruck

 OCR1A = XTAL / DEBOUNCE - 1;

ist vorhanden, weil der Timer bei jedem Überlauf bei "0" zu zählen
beginnt und dabei bereits ein Takt vergeht.

Soll der Timer also z.B.: bis 10 zählen und man würde den Wert "10"
ins OCR1A Register schreiben, dann würde der Timer bei jedem Durchlauf
eigentlich bis "11" zählen, weil

0,1,2,3,4,5,6,7,8,9,10,0,1,2,3,4,5,6,7,8,9,10

Daher müsste ich in diesem Falle wohl "9" ins Register schreiben.

Damit wäre das "-1" erklärt, aber was hat es dann mit dem angeblich
zusätzlich benötigten Timertakt zum Nachladen des Wertes des Timers im
CTC Mode auf sich? Davon hab ich im Datenblatt nichts gelesen...

Danke!

Gruß..Mark

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.