hi,
ich probiere gerade einen Timer für ein anderes Projekt zum laufen zu
bringen. Ich verwende einen Atmega162 mit 7372800 Hz. Nur der Code
springt nicht in die Interrupt Routine. Hier mal die relevanten stellen:
1
intms;
2
uint8_ts;
3
uint8_tmin;
4
5
//Timer1 Compare Match Interrupt
6
ISR(TIMER1_COMPA_vect)
7
{
8
//Milli Sekunden um 1 erhöhen
9
ms++;
10
//sind 1000 ms um?
11
if(ms==1000){
12
//ms zurücksetzen und Sekunden erhöhen
13
ms=0;
14
s++;
15
//sind 60 Sekunden um?
16
if(s==60){
17
//Sekunden zurück setzen und Minuten erhöhen
18
s=0;
19
min++;
20
}
21
}
22
}
23
24
.
25
.
26
.
27
28
//In main():
29
//CTC Modus & Vorteiler 8
30
TCCR1B|=(1<<CS11)|(1<<WGM12);
31
//Interrupt bei Compare Match
32
TIMSK=(1<<OCIE1A);
33
//Compare Wert setzen
34
OCR1A=9216-1;
der Timer soll jeder ms nen Interrupt auslösen, und die Variable ms
hochzählen.
Hast du interrupt.h includet?
Woher weist du eigentlich, das der Interrupt nicht
angesprungen wird?
Warum sind s und min nicht volatile? Die werden ja doch wahrscheinlich
von der Hauptschleife her ausgelesen?
usw. usw.
Poste doch bitte das komplette Programm!
Dann brauchen wir nicht jedes Fitzelchen Code nachzufragen.
Nimm einfach dein *.c und hänge es als Attachment an.
Das ist erstens für dich viel einfacher und zweitens kann
dann keine Information fehlen.
Dann läuft Dein Controller vermutlich nicht mit 7,... MHz sondern mit 1
MHz. Dann musst Du vermutlich die Fusebits entsprechend ändern, dass
der Controller auch weiß, dass er mit dem Quarz laufen soll und nicht
mit dem internen RC-Oszillator.
Marian wrote:
> Nein, ne Millisekunde sind 10e-4 Sekunden, also 1/1000. 1e-3 ist auch> eine Millisekunde^^ :)
Doch, eine Millisekunde sind 10^-3 Sekunden, und das sind 0,001
(Grundschule: Man nehme eine 1 und schiebe das Komma um 3 Stellen nach
links...). 10^-4 (oder 1e-4 wie manche es lieber schreiben) sind
logischerweise 0,1 ms...
EDIT: OK, 10e-4 sind natürlich 1e-3... Das ist natürlich ein völliges
Durcheinander.
Eine Möglichkeit wäre, den Timer ohne Prescaler laufen zu lassen, und
den Compare-Match-Wert auf 36864 zu setzen. Das liefert genau 5
Interrupts pro ms. Um von den 0.2 ms zu den ganzen Millisekunden zu
kommen, schachtelst Du den Code im Interupthandler einfach in einen
1:5-Software-Frequenzteiler ein, so wie Du es schon bei den ms und s
praktiziert hast.
Während 0.2 ms kann Dein Controller immer noch soviele Instruktionen
abarbeiten (ihm stehen ja 36864 Zyklen zur Verfügung), dass Du keine
Überforderung befürchten musst.
Ich hab mich mit den Zahlenwerten verhaspelt. Sorry!
Richtig ist:
7372800 Hz / 36864 = 200 Hz --> 5 ms Interruptintervall.
Das ist das kleinstmögliche dezimalsystemkompatible Intervall. Auf 1 ms
kommst Du nicht (lies: nicht ohne "Tricks"), weil 36864 nicht durch 5
teilbar ist. Für 1 ms Compare-Match-Interrupt-Intervall hat Dein Quarz
mit 7.372800 MHz einen zu krummen Wert.
OCR1A musst Du tatsächlich mit 36863 laden, wenn Du alle 36864 Zyklen
einen Überlauf wünschst (gilt nur bei Prescaler = 1).
Gibt es überhaupt einen triftigen Grund für die Verwendung eines
Baudratenquarzes? Das beschriebene Problem ist nämlich der gewaltige
Nachteil von solchen Quarzen. Die haben nunmal Frequenzen, die ein
Vielfaches von 300 Hz sind. Und alles mit ner "3" drin ist in solchen
Fällen etwas problematisch. Wenn es irgendwie geht, nimm lieber nen
Standardquarz (z.B. 8 MHz, damit lassen sich sehr schön ms-Takte
erzeugen).
Florentin S. wrote:
> Naja ist halt ne rein serielle Anwendung.
Das sagt erstmal gar nichts. Viele übliche Baudraten lassen sich auch
mit Standardquarzen mit ausreichender bis sehr guter Genauigkeit
erzeugen. Baudratenquarze brauchts eigentlich nur dann, wenn man
entweder auf irgendeine bestimmte Baudrate festgelegt ist, die mit
Standardquarzen nicht generierbar ist oder wenn man flexibel zwischen
allen üblichen Baudraten wählen können will. Teilnehmer A und Teilnehmer
B müssen sich nur auf eine Baudrate einigen. Und wenn beide Teilnehmer
µCs sind, dann braucht man sich nicht mal an die Standard-Baudraten (mit
300Hz * 2^n) zu halten...
Sehr vernünftig. Aber wenn Du wirklich 9 oder 23 oder 161 ms
quarzpräzise abzählen können willst, darfst Du halt keinen
Baudratenquarz verwenden. Ansonsten musst Du entweder eine kleine
Ungenauigkeit in Kauf nehmen (mit 7373 für den Compare Match [*]
bekommst Du 7373 / 7372800 Hz = 1.0000271 ms), oder den Fehler
softwaremäßig korrigieren (Compare Match Wert jedes n-te Mal auf 7372
herabsetzen, n passend wählen; genaueres in der Codesammlung unter "Die
genaue Sekunde"), oder Dich mit dem minimal möglichen exakten Zeitraster
von 5 ms begnügen.
[*] OCR1A dann mit 7372 laden.
Eine eigene Frage?
Dieser Thread ist über 18 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.