Hallo Leute, habe heute den ganzen So. verbracht mich in den Timer1 einzulesen. Da ich noch ein Anfänger bin, brauche ich eure Hilfe. Die Suche habe ich auch bemüht aber zu keinem Ergebnis gekommen. Arbeite mit einem atmega32 der mit 16 MHz getaktet wird. Versuche mit C zu programmieren. Mein Vorhaben ist dass ich eine Uhr programmieren möchte. Dazu will ich den Timer1 nützen der im CTC- Betrieb läuft. Soviel zu der Rechnerei: 16000000/1024=15625 so jetzt haben wir 15625 Takte pro Sekunde Jetzt soll der Timer bis 15624 zählen und dann ein Überlauf auslösen was ein Interrupt auslöst. Mein Code: //Initialisierung von TIMER1 TCCR1B |= (1 << CS12 | 1 << WGM12 | 1 << CS10); TCCR1A = 0b00000000; TIMSK |= (1 << OCIE1A); OCR1A = 15624; //Globale Interrupts freischalten sei(); //Timer1 Interrupt ISR (TIMER1_OVF_vect) { if(sek>58) { sek=0; } else { sek = sek + 1; } if(sek==0) { min = min + 1; } if(min>59) { st = st + 1; } } Wäre nett wenn mir einer sagt wo mein Denkfehler liegt.
Wenn Du schon im CTC-Modus arbeitest, dann solltest Du auch den Compare-Interrupt benutzen und nicht den Overflow-Interrupt... EDIT: Schau Dir im Datenblatt mal in der Tabelle an, wann das TOV1-Flag (das den Overflow-Interrupt auslöst) im CTC-Modus gesetzt wird, nämlich beim Erreichen von MAX (also dem maximalen Zählwert von 65535). Der wird aber nie erreicht. In diesem Fall geht es also nur mit dem Compare-Interrupt A.
Dein Timer dürfte - von Dir unbemerkt - wie am Schnürchen laufen. Nur der Overflow-Interrupt wird nie ausgelöst. Erstens weil Du ihn nicht enabled hast, zweitens, weil der Zähler in Deiner Konfiguration (CTC-Modus) nie den Stand 65535 erreicht und dann noch eins weiterzählt. Schreib also die Zeile ISR (TIMER1_OVF_vect) um auf den Output-Compare-A-Interrupt und alles sollte sofort tun wie gewünscht.
Probier's mal so:
1 | SIGNAL (SIG_OUTPUT_COMPARE1A) |
2 | {
|
3 | ...
|
4 | }
|
Ach ja..
1 | #include <avr/Interrupt.h> |
nicht vergessen einzubinden. ;)
Thilo M. wrote: > Probier's mal so: >
1 | > SIGNAL (SIG_OUTPUT_COMPARE1A) |
2 | > { |
3 | > ... |
4 | > } |
5 | >
|
keine gute Idee. Die SIGNAL Schreibweise ist veraltet. In einer der nächsten Compilerversionen wird sie komplett aussterben. Es gibt keinen Grund mehr, diese Schreibweise zu lehren oder vorzuschlagen.
>ISR (TIMER1_OVF_vect)
wie jetzt, das ist doch nicht richtig oder??
Das ist doch der Überlauf....
@ Karl heinz: Wo iss'n eigentlich der Unterschied? Dachte immer, dass beim Verlassen der Routine das I-Flag mal gesetzt wird, mal nicht ('ret' und 'reti'). Liege ich da total falsch?
Max wrote: >>ISR (TIMER1_OVF_vect) > > wie jetzt, das ist doch nicht richtig oder?? > > Das ist doch der Überlauf.... Genau. Das ist nicht richtig. Der Timer geht nicht in einen Überlauf, sondern in einen Compare Match ABer der Compare Match den du haben willst heist TIMER1_COMPA_vect (weil es 2 Compare Einheiten gibt. A und B) und nicht TIMER1_COMP1_vect ISR( TIMER1_COMPA_vect ) { ... }
der Vorschlag hat jetzt funktioniert. >SIGNAL (SIG_OUTPUT_COMPARE1A) >{ > ... >} Wie ist es jetzt richtig? Wenn "Signal" veraltet ist?
Thilo M. wrote: > @ Karl heinz: > Wo iss'n eigentlich der Unterschied? > Dachte immer, dass beim Verlassen der Routine das I-Flag mal gesetzt > wird, mal nicht ('ret' und 'reti'). > Liege ich da total falsch? Ja. Prinzipiell besteht funktional kein Unterschied zwischen beiden Schreibweisen. Es ist nur so, dass bei SIGNAL die Interrupt Vektoren eigenwillige Namen bekommen haben. Irgendwann hat man beschlossen, den Vektornamen immer aus dem Namen im Atmel- Datenblatt mit einem angehängten _vect zu bilden. http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Veraltete_Funktionen_zur_Deklaration_von_Interrupt-Routinen
Macht Sinn! ;) Habe schon länger nicht mehr im Tutorial gestöbert.
>ISR( TIMER1_COMPA_vect ) >{ > ... >} Hat jetzt auch funktioniert, danke für die schnelle Hilfe. nach 4 Min habe ich noch keine Abweichung. Wie zuverlässig ist der Externe Quarz??? Kommt mit der Zeit eine Abweichung rein???
Max wrote: >>ISR( TIMER1_COMPA_vect ) >>{ >> ... >>} > > Hat jetzt auch funktioniert, danke für die schnelle Hilfe. > > nach 4 Min habe ich noch keine Abweichung. > > Wie zuverlässig ist der Externe Quarz??? > Kommt mit der Zeit eine Abweichung rein??? Wahrscheinlich. Kann aber durchaus sein, dass du erst morgen Abend eine Abweichung von 1 Sekunde siehst. Also: Lass mal laufen und sieh in 1 Stunde noch mal nach. Wenn die Abweichung noch nicht sehr gross ist, dann lass die Uhr bis morgen abend laufen. Stell die Abweichung in 24 Stunden fest und rechne daraus die tatsächliche Quarz-Frequenz aus.
> OCR1A = 15624;
Du musst noch ein Zähler deines errechneten Wertes abziehen. Dann ist es
Korrekt. (OCR1A = 15623); Die Uhr wird zwar immernoch nicht 100%ig genau
sein, aber die Abweichung ist minimal.
Es gibt einen Weg, die Ganggenauigkeit zu erhöhen, nämlich in dem man
einen Kondensator im Schwingkreis durch ein Drehko ersetzt und mit einem
Frequenzzähler den Quarz eicht. Allerdings darf man mit der Prüfspitze
des Frequenzzählers nicht direkt am Schwingkreis messen, da dieser
Messstrom das Ergebnis des Schwingkreises verfälschen würde....
Man schreibt ein kleinen "Eichcode", der einfach nur einen Portpin so
schnell wie möglich high-low schaltet; natürlich im Zusammenhang mit
einem Timer, der die Quarzperioden zählt. Mit dem Drehko kann man dann
die Schwingfrequenz des Quarzes leicht ändern. Die Prüfspitze des
Frequenzzählers ist an den Portpin anzulegen und mit Hilfe des Drehkos
auf einen errechneten Wert einzustellen.
Mit dieser Methode erreicht man Ganggenauigkeiten, die etwa eine Sekunde
pro Jahr deutlich unterschreiten.
Bitte beachten: manchmal verändert schon die blosse Berührung der
elektronischen Bauteile die Schwingfrequenz. Daher sind die
Messergebnisse nur dann genau, wenn weder Dreko noch Quarz berührt
werden.
Bei der Wahl der Bauteile kann man noch eine etwas unautodoxe
Daumenregel anwenden: je grösser das Gehäuse, desto höher die
wahrscheinlichkeit, daß sie Temperaturstabiler arbeiten.
@ Niels: 15624 ist schon korrekt! (0 .. 15624 => 15625 Schritte) Und Eichen tut das Eichamt. ;) Du meinst 'Justieren', das genaue Messen ist 'Kalibrieren'. Sorry wegen der Haarspalterei.
Thilo M. wrote: > @ Niels: > 15624 ist schon korrekt! (0 .. 15624 => 15625 Schritte) Ich hätte gestern nicht soviel saufen sollen.. Sorry, 15624 ist natürlich korrekt.
>Wie zuverlässig ist der Externe Quarz??? >Kommt mit der Zeit eine Abweichung rein??? Schau doch im Datenblatt Deines Quarzes nach. Da stehen die Genauigkeiten drin. Bei guten Standardquarzen beträgt sie grob 10 ppm = 10^-5 (ppm = parts per million = 10^-6). Und jetzt rechnen: Ein Tag hat 24 60 60 s = 86400 s. Das multipliziert mit 10^-5 liefert 0.864 s. Ergebnisa also: Pro Tag kannst Du eine Abweichung von ungefähr knapp einer Sekunde erwarten.
Oder wie Niels schrieb, Drehkondensator, um den Quarz auf die exakte Frequenz zu 'ziehen' und bei konstanter Temperatur betreiben, dann sollte die Abweichung minimal bleiben.
>und bei konstanter Temperatur betreiben, dann sollte die Abweichung minimal >bleiben. Dann bleibt nur noch die alterungsbedingte Frequenzdrift des Quarzes übrig (keine Ahnung wie groß die ist).
OK, ich werde mal sehen wie es läuft... Habe noch eine Frage zu dem Timer1: der Timer soll jetzt ein Interrupt bei 15625 Takten auslösen. Ich lege jetzt im OCR1A die Obergrenze wann es so weit ist. Kann ich dem Timer auch sagen ab wann er anfangen soll und dann mit dem Überlauf arbeiten? Ich könnte mir vorstellen dass man ein Wert im Interrupt in den Datenregister (TCNT1) rein schreibt ab wann er weiter laufen soll. Macht man sowas? Oder welche Möglichkeiten gibt es noch? Gruß Max
>Kann ich dem Timer auch sagen ab wann er anfangen soll
Na klar.
Da steht dir Tür und Tor offen.
Max wrote: > Kann ich dem Timer auch sagen ab wann er anfangen soll und dann mit dem > Überlauf arbeiten? Diese Methode nennt sich "autoreload" und wird von der ATmega-serie nicht unterstützt. Man kann zwar ein soetwas Softwaremässig nachbilden, aber das ist dann nicht mehr so genau. Meiner Meinung nach gibt es dafür aber auch keinen Grund, weil CTC im Prinzip das selbe macht. Wenn du mit Autoreload arbeiten möchtest, müsstest du in die 80C51-kompatible Welt umsteigen. :)
Max wrote: > Kann ich dem Timer auch sagen ab wann er anfangen soll und dann mit dem > Überlauf arbeiten? Im Prinzip kannst du. Allerdings musst du dann in der ISR den Timer wieder neu setzen. Und genau hier liegt der Haken. Du kannst nicht mit 100% Sicherheit sagen, wieviele Takte von der Auslösung des Interrupts bis zum Neusetzen des Timers vegehen. Hängt ja unter anderem auch davon ab, bei welchem Befehl der Interrupt auftritt. Der Befehl wird ja noch in jedem Fall vollständig abgearbeitet. Nun gibt es aber Befehle die 1 Takt dauern und es gibt Befehle die 2 Takte dauern. > > Ich könnte mir vorstellen dass man ein Wert im Interrupt in den > Datenregister (TCNT1) rein schreibt ab wann er weiter laufen soll. > > Macht man sowas? Oder welche Möglichkeiten gibt es noch? Ja. macht man auch. Aber wenns wirklich auf den einzelnen Takt genau sein muss, dann ist CTC das Beste was du kriegen kannst.
>Mit dieser Methode erreicht man Ganggenauigkeiten, die etwa eine Sekunde >pro Jahr deutlich unterschreiten. Da träumst Du aber, junger Freund.
@Max Übrigens wirst du deine Uhr nicht mit maximaler Genauigkeit einstellen können. Der Grund dafür ist, dass du einen Vorteiler von 1024 benutzt. Nehmen wir mal an, du bekommst durch nachmessen heraus, dass dein Quarz in einem Tag um 512 Schwingungen zuviel macht. Was tust du? Benutzt du weiterhin 15624 als Endwert, dann geht deine Uhr zu schnell. Benutzt du 15625 dann geht die Uhr zu langsam. http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC
Der Dude wrote:
> Da träumst Du aber, junger Freund.
Natürlich spreche ich hier nicht von einem 32.768Khz-Uhrenquarz im 0,2mm
Gehäuse.
Nein, ich hatte mal beruflich mit der Justage von Quarzen zur
Zeitmessung zu tun. Wenn die Schaltung an einem einigermaßen
temperaturstabilen Umgebung gelagert wird und so wenig wie möglich
bewegt wird, funktioniert das!
Es gibt lediglich ein paar oben bereits erwähnte Dinge, die bei der
Justage zu beachten sind. Aber diese Methode hat sich bereits mehrfach
für mich bewährt. Die Ganggenauigkeit, die man mit hochfrequenten
Quarzen erreichen kann ist wirklich sagenhaft.
>http://www.mikrocontroller.net/articles/AVR_-_Die_...
OK, danke werde es mir morgen durchlesen
Jetzt gehts aber ins Bett, morgen geht es wieder in die Schule.
Nochmal DANKE an ALLE für die Hilfe.
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.