mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer im CTC-MODE


Autor: Sascha Dürkes (plutoonline)
Datum:

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

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie schaltest Du denn den Pin um (wär echt schön, wenn Du das
komplette Programm geschickt hättest...)? Etwa per Software?

Autor: johnny.m (Gast)
Datum:

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

Autor: Sascha Dürkes (plutoonline)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@johnny.m
wie gewünscht......

void Init_Timer_2(void)
{
TCCR2  = (1 << WGM21)|(1 << CS20);
TIMSK |= (1 << OCIE2);
OCR2   = 100;
}

SIGNAL(SIG_OUTPUT_COMPARE2)
{
PORTB ^= (1 << PB0);
}

int main (void)
{
DDRB  |= (1<<PB0);
sei();
Init_Timer_2();
}

Autor: johnny.m (Gast)
Datum:

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

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#define SIGNAL(x) ISR(x)

Könnte gehen, wenn man es in das Hauptprogramm schreibt, oder?

Autor: Sascha Dürkes (plutoonline)
Datum:

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

Autor: johnny.m (Gast)
Datum:

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

Autor: Sascha Dürkes (plutoonline)
Datum:

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

Autor: Sascha Dürkes (plutoonline)
Datum:

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

Autor: johnny.m (Gast)
Datum:

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

Autor: Sascha Dürkes (plutoonline)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab OCR2=18 initialisiert und bekomme 25us raus da kann doch
irgenwas nicht stimmen:-(

So langsam bin ich am verzweifeln.

Autor: Björn (Gast)
Datum:

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

Autor: johnny.m (Gast)
Datum:

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

Autor: Sascha Dürkes (plutoonline)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab mal ein programm angehängt.
Was sollte eures erachtens am Pin B0 rauskommen?
Bei mir kommt 2ms High und 18ms Low raus.
Rein rechnerisch sollte 0,3ms High und 3,24ms Low rauskommen, oder
liege ich da falsch?

Autor: Sascha Dürkes (plutoonline)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
achso bei 4MHz.

Autor: Sascha Dürkes (plutoonline)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab mal ein bischen rumgetestet, also bei ORC2 kleiner 100
verändert sich nix mehr.
Bei allen Werten unter 100 nacht er 25us.
Bei Werten über 100 scheint alles korrekt zu laufen.
Hat jemand dafür eine Erklärung?

Autor: johnny.m (Gast)
Datum:

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

Autor: johnny.m (Gast)
Datum:

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

Autor: Hubert.G (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was macht dein Programm wärend der Timer läuft, ich sehe keine
Endlosschleife in main, sowas wie  for(;;){}

Autor: johnny.m (Gast)
Datum:

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

Autor: Sascha Dürkes (Gast)
Datum:

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

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.