www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer0 bei ATMega 169


Autor: S. N. (sp00ky-n1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo allerseits,

sitze hier vor einem kleinen Problem und kommen einfach nicht dahinter, 
wo der Fehler steckt. Ich muss auf einem einen ATMega 169 eine Uhr 
programmieren. Habe mir auch schon das Tutorial dazu angeschaut und 
damit versucht, eine Lösung zu finden.
Soweit funktioniert das auch: Ich kann die Uhr einstellen, die Zeit wird 
korrekt dargestellt etc.
Das Problem ist der Timer0 den ich verwenden muss. Der Prozessortakt 
beträgt 2 MHz, habe mir einen Prescaler von 8 gewählt und verwende den 
CTC-Modus des Timers. gezählt wird bis 249, so dass bei jedem 250. Takt 
ein Interrupt erzeugt wird. Somit habe ich jede Millisekunde einen 
Interrupt. Um nun auf eine Sekunde zu kommen, muss ich doch einfach bis 
1000 zählen?
Wenn ich das aber mache, läuft die Uhr etwa 8 mal zu langsam!
Ich zähle jetzt nur noch bis 125, damit treffe ich etwa die Sekunden. 
Ich hab aber keinen Plan, an was das liegen könnte? Dachte auch schon 
mal, dass vielleicht der Interrupt Handler zu lang ist, aber der braucht 
keine Millisekunde (er braucht nur 170µs) und ist dann fertig.

So wie das Programm jetzt läuft, läuft die Uhr nach einer halben Stunde 
Betrieb schon 22s vor, das könnte ich natürlich noch ändern indem ich 
bis zu einem höheren Wert zähle.

Ich wüsste aber dennoch gerne, woher dieses Problem kommt??

Gruß,
Sebastian.

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

mal ganz einfach gesagt: Deine Rechnung stimmt, also muß Dein Programm 
einen Fehler haben.

Das kennen wir aber nicht...

Gruß aus Berlin
Michael

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wenn ich das aber mache, läuft die Uhr etwa 8 mal zu langsam!

Schau Dir mal die FUSE Einstellung an!
Bin mir nicht sicher aber meim Mega88 ist standart Einstellung
Fclock/8.

Vielleicht ist das dein Problem!

gruß
Jürgen

Autor: wjunky (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du den Prescaler wirklich korrekt gesetzt? Nach 8 kommt 64, was den 
Faktor 8 erklären könnte...
Poste mal den relevanten Sourcecode.
Woher bekommt der µC seinen Takt? Wirklich sauberen Takt bekommt man 
glaube ich nur von einem externen Quarz.
Macht der µC noch irgend etwas anderes außer die Uhr zu benutzen? 
A/D-Conversionen mit Sleep halten meines Wissens nach bspw. die Clk_I/O 
und damit die Clk_T0 aus...

Autor: S. N. (sp00ky-n1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe den A/D Wandler ausgeschaltet. Der Takt kommt vom internen Quarz, 
der ist natürlich immer noch nicht wahnsinnig genau. Er müsste aber doch 
in etwa so genau sein.
Hier mal meine Timer Initialisierung:
.MACRO Timer_Initialization
  ldi temp1, 0b00001010    ;set Timer0 Mode (CTC with 8 as presacler)
  out TCCR0A, temp1

  ldi temp1, 0x00        ;set start value
  out TCNT0, temp1

  ldi temp1, 0xF9        ;set maximum value, i.e. 2Mhz/(8*250)=1 kHz
  out OCR0A, temp1

  ldi temp1, 0x02        ;enable Compare Match Interrupts for Timer0
  sts TIMSK0, temp1

  ldi temp1, 0x03        ;clear Output Compare Match Flags
  out TIFR0, temp1
.ENDMACRO
Die Fuse Einstellungen überprüfe ich nachher mal, wenn ich daheim bin. 
Sitz grad in Messtechnik fest^^

Und zum Interrupt Handler:
Timer_Interrupt_Handler:
  cli              ;disable interrupts
  
  ldi temp1, 0x3b
  ldi temp2, 0x17

  dec counter          ;1 second is reached after 8 interrupts
  brne Return

;  dec counter2
  ldi counter, 0x7D
;  brne Return

;  ldi counter2, 0x04      ;reset counter

  cp temp1, second      ;check, if the seconds have reached 59,
  brne increase_sec      ;if not, increase them
  
  cp temp1, minute      ;check, if also the minutes have reached 59,
  brne increase_min      ;if not, increase them and reset seconds

  cp temp2, hour        ;check, if hour has reached 23, if not, increase them
  brne increase_hour      ;and reset seconds and minutes

  ldi second, 0x00      ;reset time if it switches from 23:59:59 to 00:00:00
  ldi minute, 0x00
  ldi hour, 0x00

  call Output
  
  sei

  reti
In den Subroutinen increase_sec, increase_min und increas_hour werden 
natürlich auch jedes Mal ein Output gestartet, Interrupts erlaubt und 
mit reti abgeschlossen.

Das auskommentierte counter2 stammt noch von meiner ersten Rechnung, die 
Schleife war über eine innere mit 250 und die äußere mit 4 realisiert.
Gruß.

Autor: S. N. (sp00ky-n1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich sollte noch hinzufügen: In der Simulation liefert das Programm mit 
den im ersten Beitrag genannten Einstellungen Ausgabe in Abständen von 
exakt einer Sekunde... Denke daher, dass das Problem irgendwo im µC 
liegt. Habe es schon auf 2 unterschiedlichen ausprobiert, gleiches 
Problem...

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich tendiere auch dahin, dass die CKDIV8-Fuse programmiert ist 
(Auslieferungszustand). Ist ein sehr verbreiteter Fehler.

Autor: wjunky (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
cli und sei kannst du dir sparen. Der Interrupt Call löscht I 
automatisch und reti setzt I wieder.

Das 1:8 Verhältnis wird von der Fuse kommen.
Die 22s auf 30min sind 1,2% Abweichung. Das könnte am internen Takt 
liegen, der ist halt nicht so toll...

Lösung:
Fuses prüfen und ggf. richtig programmieren.
Externen Quarz für Taktung benutzen; alternativ: die Countervariable zum 
Word machen und nicht Sekunden, sondern Minuten zählen (sekundengenaue 
Anzeige ist ja trotzdem möglich). Dann kann man den Wert recht genau 
anpassen. Das löst allerdings keine Probleme bei 
Temperaturabhängigkeiten...
Daher auch mal überlegen, den µC zwischendurch in Idle-Sleep zu setzen, 
und ungerauchte Devices abzuschalten (AC muss glaube ich explizit 
ausgeschaltet werden), um den Chip kühl zu halten.

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.