Timer im CTC-MODE

OP #361115
Lesenswert?

Hallo ich habe ein kleines Problem mit dem Timer im CTC-Modus
auf einem Mega8 mit 4MHz.

Egal was ich in OCR2 einstelle es verändert sich nix...
Der Timer sollte bei 4Mhz ohne Prescaler laufen.
Bei OCR2=100 sollte also alle 25us der Timer ausgelöst werden.
Ich lasse im Programm vom Timer einen Pin toggeln, was auch
funktioniert,
nur nicht in der richtigen Frequenz.
Und wenn ich das OCR2 verändere ändert sich an der Frequenz laut Oszi
gar nichts.


[so habe ich den Timer initialisiert]
void Init_Timer_2(void)
{
TCCR2  = (1 << WGM21)|(1 << CS20);
TIMSK |= (1 << OCIE2);
OCR2   = 100;
}

Vielen Dank schonmal für eure Hilfe!
Gast #361117
Lesenswert?

Magst net mehr? Na gut, kleiner Tip: Setze das COM20-Bit im TCCR2 und
miss direkt am OC2-Pin. Wenn sich dann was ändert, wenn Du OCR2
änderst, dann ist es ein Fehler im Programm. Ansonsten ist es zunächst
mal ziemlich mysteriös...
Gast #361119
Lesenswert?

Und haste das mit dem OC2-Pin (PB3) mal ausprobiert? Oder ist der
anderweitig belegt und nicht zugänglich? Am Programm an sich kann ich
keinen Fehler finden. Änderst Du das OCR2 durch neuprogrammieren?

BTW: Mach mal bei Gelegenheit ein Update vom WINAVR. SIGNAL ist
mittlerweile veraltet. Das geht jetzt mit ISR. Wie es geht steht im
AVR-GCC-Tutorial. Die aktuelle AVR-libc-Version unterstützt zwar noch
die alten SIGNALs, aber die Frage ist, wie lange noch?
OP #361121
Lesenswert?

Also muß es wohl so heissen -->

ISR (TIMER2_COMP_vect)
{
PORTB ^= (1 << PB0);
}

aber ich glaube nicht das daher der fehler kommt?!
Der Timer läuft ja, nur nicht so wie er soll.

Habe ich eigentlich den Timer richtig initialisiert?

Kann leider im moment nichts testen in auf der Arbeit :-(
Gast #361122
Lesenswert?

Wie schon gesagt, für das, was Du ursprünglich anscheinend wolltest,
scheint die Initialisierung korrekt zu sein. Bei so kurzen Zeiten würde
ich persönlich aber keinen Pin in einer ISR umschalten sondern eben das
Hardware-Feature nutzen. Dafür ist es da. Wenn Du die Einstellungen so
wie oben beibehältst und zusätzlich das COM20 im TCCR2 setzt, toggelt
der PB3 automatisch bei jedem Compare. Wenigstens zum testen würd ich
es ausprobieren...
OP #361123
Lesenswert?

@johnny.m
Ich will natürlich nicht nur einen Pin toggeln sondern ein bestimmtes
Signal erzeugen. Das Pin toggeln ist nur zum testen gedacht.
Solange ich aber nichtmal das auf die reihe bekommen brauch ich mit dem
rest erst gar nicht anzufangen.

Vielen Dank erstmal, ich werde dann berichten wenn ich das heute Abend
getestet habe.
OP #361124
Lesenswert?

Bin gestern leider nicht zu testen gekommen.
Aber kann es sein das ich bei der Initialisierung einen fehler gemacht
habe?
Muß vielleicht erst OCR2 gesetzt werden und dann der Timer enabled
werden?

void Init_Timer_2(void)
{
TCCR2  = (1 << WGM21)|(1 << CS20);
TIMSK |= (1 << OCIE2);
OCR2   = 100;
}
Gast #361125
Lesenswert?

Nö, das dürfte kaum einen Unterschied machen. Wenn Du den Timer startest
und danach erst das OCR schreibst, ist das schlimmste was Dir passieren
kann, dass das TCNT zum Zeitpunkt des Schreibens bereits einen höheren
Wert hat und dann eben einmal überläuft. Danach müsste aber der
korrekte Takt rauskommen.
Gast #361127
Lesenswert?

Welche Taktfrequenz verwendest du denn...?

Variiere mal OCR2 zwischen 15 und 25. Wenn immer 25µs herauskommen,
kann es sein das die minmialste Impulslänge welche du mit mit diesem
Takt erzeugen kannst 25µs ist.

Stimmen denn die Längen bei höheren Werten für OCR2?

Hatte ein ähnliches Problem im µs-Bereich. Brauchte 10µs aber konnte
minimal 14,3 erzeugen. Hab dann nen größeren Quarz verwendet und alles
funktionierte bestens.
Gast #361128
Lesenswert?

@Björn:
Der arbeitet, wie er ganz oben geschrieben hat, mit 4 MHz. Da dürfte
das keine Rolle spielen. Er sagt ja auch nicht, dass er nicht unter
einen bestimmten Wert kommt, sondern dass sich unabhängig von den
OCR-Werten angeblich nix ändert. Selbst mit 100 hat es ja anscheinend
nicht geklappt!
Gast #361132
Lesenswert?

> if (delay == 720) {delay=0;PORTB |= (1 << PB0);}
> if (delay <= 80) {PORTB |= (1 << PB0);}

Dir scheint nicht klar zu sein, dass wenn delay 720 ist auch das zweite
if ausgeführt wird, da Du delay in der ersten if-Abfrage ja wieder auf
Null setzt. Da wäre ein else if angebracht!

Abgesehen davon solltest Du keine static-Variable in einer ISR
deklarieren. Mach delay global!

Hast Du es denn wenigstens mal ohne die ganzen Abfragen in der ISR
ausprobiert? Oder einfach mal, wie ich Dir geraten hatte, ohne
Interrupt, sondern nur hardwaremäßig den Pin toggeln?
Gast #361133
Lesenswert?

Ach ja, wenn Du natürlich jetzt mit so niedrigen Werten (OCR2 = 18)
arbeitest, wundert es mich natürlich nicht, dass es schief geht. Was
glaubst Du, wie lange die Bearbeitung der ISR dauert? Auf jeden Fall
länger als 18 Taktzyklen. Dadurch entgeht Dir auf jeden Fall mindestens
jeder zweite Interrupt, möglicherweise eher mehr!

Der Einsprung in den Interrupt-Vektor dauert beim Mega8 4 Taktzyklen.
Dann kommen 3 Zyklen für den Sprungbefehl in die ISR dazu. Dann werden
Register gesichert, was auch noch mal 10-15 Zyklen dauern dürfte. Dann
kommt Deine if-Abfrage (sicher so um die 30-40 Zyklen, geschätzt). Der
Am Ende werden die Register wieder geladen (noch mal 10-15 Zyklen) und
der Rücksprung dauert noch mal 4 Zyklen. Dann noch mindestens ein
Befehl im Hauptprogramm (mindestens ein Zyklus) und erst dann kann der
nächste Interrupt bearbeitet werden!

Also ist es verständlich, dass sich bei Werten unter 100 nix mehr
ändert!
Gast #361135
Lesenswert?

Gehe mal davon aus, dass der Compiler hier automatisch eine
Endlosschleife einfügt. Andernfalls hätte Sascha gar nix gemessen...
Aber der Einwand ist durchaus berechtigt. Also ein while(1); oder
for(;;); ans Ende von main.
Gast #361136
Lesenswert?

So ein Mist, hätte ich ja auch selbst drauf kommen können.
Da ist meine Timerroutine wohl etwas zu lang für die kurze Zeit.
Da muß ich an die Sache etwas anders dran gehen.
Mal sehen wie ich das Ganze Umsetzen kann.
Vielen Dank vorerst mal an alle!!!!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren