Hallo, um eine sehr genaue Uhrzeit zu bekommen, ist es ja denke ich besser, wenn möglichst wenige ISR vorkommen, da hier ja wieder Taktzyklen verloren gehen. Nun überlege ich, wie ich am besten den Vorteiler mit dem OCR1A Register kombiniere. Habe hier 2 Varianten, welche ist besser? (Quarz mit 16Mhz verwende ich) 1. OCR1A auf 64000 setzen TCCR1B |= (1<<CS10) => Systemtakt Nun zähle ich in der ISR eine Variable hoch bis 250, dann habe ich 250*64000=16.000.000. Also 1 Sekunde. 2. OCR1A auf 62500 setzen TCCR1B |= (1<<CS12) = Takt = 16.000.000 / 256 = 62500 Nun zähle ich immer bis 62500 und brauche in der ISR nicht mehr irgendwelche Variablen hochzuzählen.
Hallo, wenn der Timer im CTC-Mode läuft ist das doch fast völlig uninteressant. Wenn z.B. alle 10ms ein Timer-IRQ ausgelöst wird dann passiert der auch alle 10ms. Wenn jetzt die IRQ-Routine für den Zähler bis 100 (1s) ein paar Takte später ausgeführt wird, dann wird die aktuelle Sekunde etwas später aktualisiert werden. Der Timer selbst läuft davon unbeeindruckt ja weiter und löst pünktlich 10ms später den nächsten IRQ aus. Die IRQ-Routine darf natürlich nicht länger als 10ms dauern, sonst wird der nächste IRQ verpasst, aber das soll sie sowieso nie. Gruß aus Berlin Michael
Jürgen Hems wrote: > Hallo, > um eine sehr genaue Uhrzeit zu bekommen, ist es ja denke ich besser, > wenn möglichst wenige ISR vorkommen, da hier ja wieder Taktzyklen > verloren gehen. Das wäre schlimm, wenn dem so wäre. Man muß die Interrupts nur so programmieren, daß die Einsprungzeit und Verzögerungen durch andere Interrupts keine Rolle spielen. Entweder Hardware-Reload bzw. Clear on Compare oder Addition des Timers zur gewünschten Verkürzung. Dann kann man soviele Interrupts verwenden, bis der Arzt kommt. > Nun zähle ich immer bis 62500 und brauche in der ISR nicht mehr > irgendwelche Variablen hochzuzählen. Du kannst es versuchen, aber ich hatte bisher noch nie einen Quarz mit genau 16.000.000Hz. Man muß daher für Uhrenanwendungen noch Korrekturwerte addieren (z.B. je Sekunde). Peter
@ Jürgen Hems (misteret) >um eine sehr genaue Uhrzeit zu bekommen, ist es ja denke ich besser, >wenn möglichst wenige ISR vorkommen, da hier ja wieder Taktzyklen >verloren gehen. Falsch, wie Peter bereits bemerkte. Eine ISR verschluckt keine Takte, wenn sie richtig programmiert ist. Siehe Interrupt. > Nun zähle ich in der ISR eine Variable hoch bis 250, dann habe ich > 250*64000=16.000.000. Also 1 Sekunde. Siehe AVR - Die genaue Sekunde / RTC MFG Falk
Hoi Hoi! Ich nutze einen Compare Match Interrupt für eine RTC und schreibe das ganze in ein Array, der Interrupt wird alle 0.01 Sekunden ausgelöst:
1 | ISR(TIMER1_COMPA_vect) { |
2 | rtc[2]++; |
3 | // hunderstel sek
|
4 | if (rtc[2] > 99 ) { |
5 | rtc[2] = 0; |
6 | rtc[1]++; |
7 | }
|
8 | // sekunden
|
9 | if (rtc[1] > 59 ){ |
10 | rtc[1] = 0; |
11 | rtc[0]++; |
12 | }
|
13 | // minuten
|
14 | if (rtc[0] > 9 ){ |
15 | rtc[0] = 0; |
16 | }
|
17 | }
|
18 | |
19 | void rtc_start() { |
20 | sei(); |
21 | OCR1A = 19999; |
22 | TCCR1B = 0b00001010; |
23 | TIMSK |= 0b00010000; |
24 | }
|
Wie gut meine Lösung ist... ka, für mich macht sie was sie soll ;) Du kannst dir auch das Array sparen und nur einen 16Bit Zähler inkrementieren mit den hunderstel sekunden. Dann kannst du aber nur max ~10 Minuten erfassen. Nach 9 Minuten wird bei dem o.g. Code wieder von vorn angefangen zu zählen, bei mir ist das gewollt, das ist ja aber leicht zu ändern. Mfg, Peter
Es genügt, die Sekunden jede Sekunde zu bearbeiten: ISR(TIMER1_COMPA_vect) { rtc[2]++; // hunderstel sek if (rtc[2] > 99 ) { rtc[2] = 0; rtc[1]++; // sekunden if (rtc[1] > 59 ){ rtc[1] = 0; rtc[0]++; // minuten if (rtc[0] > 9 ){ rtc[0] = 0; } } } } oder wie ich schreiben würde: ISR(TIMER1_COMPA_vect){ if (++rtc[2] > 99 ){rtc[2] = 0; if (++rtc[1] > 59 ){rtc[1] = 0; if (++rtc[0] > 9 ){rtc[0] = 0;} } } } oder eine komplette Uhr mit Datum und Schaltjahr bis 2099: dm[12]={31,28,31,30,31,30,31,31,30,31,30,31};//ohne Schaltjahr ISR(TIMER1_COMPA_vect){ if(++rtc[6] > 99 ){rtc[6] = 0;//hundertstel if(++rtc[5] > 59 ){rtc[5] = 0;//Sek if(++rtc[4] > 59 ){rtc[4] = 0;//Min if(++rtc[3] > 23 ){rtc[3] = 0;//Std if(++rtc[2] > dm[rtc[1]]){rtc[2] = 0;//Tag if(++rtc[1] > 11){rtc[1] = 0;//Mon if(++rtc[0] & 3){dm[2]=28;}else{d[2]=29;}//Jahr } } } } } } } ungetestet, aus dem Stegreif getippt
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.