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 ;-)
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...
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....?!!
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?
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