www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Genaue Uhr - Frequenzteiler


Autor: Jürgen Hems (misteret)
Datum:

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

Autor: funkuhrpersönlich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
eine Funkuhr ist sehr genau

Autor: Michael U. (amiga)
Datum:

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

Autor: Peter Dannegger (peda)
Datum:

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

Autor: Falk Brunner (falk)
Datum:

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

Autor: Peter (Gast)
Datum:

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

void rtc_start() {
  sei();
  OCR1A = 19999;
  TCCR1B = 0b00001010;
  TIMSK |= 0b00010000;
}

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

Autor: eProfi (Gast)
Datum:

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

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.