mikrocontroller.net

Forum: Compiler & IDEs 100ms Takt mit 16Bit Timer


Autor: Michael Korb (michaelkorb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für mein aktuelles Projekt benötige ich einen möglichst genauen 100ms 
Zyklus. Ich setze den Atmega128 ein mit einer Taktfrequenz von 7,372800 
MHz. Demnach kommt nur ein 16Bit Timer mit Vorteiler 1024 in Frage, der 
bei Erreichen des Vergleichswertes von 720 einen Compare-Interrupt 
auslöst. Trotz eingehender Studie der Datenblätter und zahlreicher 
Versuche will es einfach nicht gelingen. Mit einem 8Bit Timer war ich 
bereits erfolgreich, der 16Bit will einfach nicht das tun was ich will. 
Irgendein Flag sitzt wahrscheinlich falsch.

// 16-Bit-Zähler initialisieren
void initZyklusTimer()
{
  TCCR3B = (1<<CS30) | (1<<CS32);  // Vorteiler 1024
  TCCR3C = (1<<FOC1A);    // Output Compare Match
         // Comparewert
  OCR3CH = 5;
  OCR3CL = 80;
  ETIMSK = (1<<OCIE3A);  // Match Interrupt Kanal A
  ETIFR = (1<<OCF3A);
}

// Interrupt-Routine Timer 3 CompareMatch Kanal A
ISR (TIMER3_COMPA_vect)
{
}

Wer kann helfen?

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du einen 100ms-Takt brauchst, dann musst Du auch dafür sorgen, dass 
der Timer, wenn die 100 ms um sind, also der Compare-Wert erreicht ist, 
zurückgesetzt wird und bei 0 wieder zu zählen anfängt. Du musst ihn also 
im CTC-Modus betreiben. Den musst Du allerdings nach Datenblatt 
einstellen, das macht der Timer nicht von allein...

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was geht denn nicht? Wird die ISR nicht angesprungen, stimmt das Timing 
nicht...?

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> OCR3CH = 5;
> OCR3CL = 80;
Was soll das denn?

1.: Wenn Du mit WINAVR-C programmierst, solltest Du zum Zugriff auf 
16-Bit-Register auch die in der Headerdatei definierten 16-Bit-Register 
benutzen, allein schon wegen der korrekten Reihenfolge beim Zugriff, 
über die Du Dir dann keine Gedanken mehr machen musst. Also anstatt 
OCR3CH und OCR3CL einfach OCR3C nehmen. In diesem Fall ist die 
Reihenfolge allerdings tatsächlich (zufällig?) richtig...

2.: 5*256 + 80 = 1360. Und das ist definitiv nicht gleich 720! Ich weiß 
nicht, was Du da gerechnet hast, aber so stimmts definitiv nicht. Und tu 
Dir selbst und anderen einen Gefallen und benutze beim getrennten 
Schreiben von Low- und High-Byte keine Dezimalzahlen. Am besten aber 
erst gar keine getrennten Zugriffe, zumindest nicht dann, wenn es die 
Möglichkeit gibt, die 16-Bit-Register als solche anzusprechen (siehe 1.) 
...

3.: Fazit: Wenn es laufen soll, dann Timer im CTC-Modus betreiben 
(Tabelle im Datenblatt gucken, WGM-Bits korrekt setzen) und schreiben
OCR3C = 720;
Dann klappts auch mit den Nachbarn...

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ja, mit der 720 kriegste übrigens auch Probleme. Das OCR3C kann 
nicht direkt als TOP-Wert der CTC verwendet werden. Außerdem würde der 
Pin OC3C mit dem Wert nur alle 100 ms umgeschaltet, was eine Periode von 
200 ms ergäbe. Also sinnvolle Vorgehensweise: CTC-Modus mit OCR1A oder 
ICR1 als TOP. In das TOP-Register die 720 reinschreiben, OCR3C mit 
1/2*720 = 360 beschreiben und den Pin entsprechend konfigurieren. Dann 
sollte es funktionieren und Du hast einen echten 100ms-Takt.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Upps, muss oben natürlich "OCR3A" und "ICR3" heißen. So langsam werde 
ich wach...

Autor: Michael Korb (michaelkorb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank Leute,

der entscheidende Fehler war der CTC-Modus, den ich nicht eingeschaltet 
hatte. Mit dem hier funktioniert es:

// 16-Bit-Zähler initialisieren
void initZyklusTimer()
{
  // CTC mit OCR3A als TOP, Vorteiler 1024
  TCCR3B = (1<<WGM32) | (1<<CS30) | (1<<CS32);
  TCCR3C = (1<<FOC1A);    // Output Compare Match
  OCR3A = 720;
  ETIMSK = (1<<OCIE3A);  // Compare Match Interrupt Kanal A
  ETIFR = (1<<OCF3A);
}

Bei 7,372800 MHz und Vorteiler 1024 ergibt sich ein Comparewert von 720 
für 100ms.

Autor: Philipp Burch (philipp_burch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Michael,

wenn es sich vermeiden lässt, solltest du nicht unbedingt den CTC-Modus 
verwenden. Aus dem einfachen Grund, das du den Timer dann nur für genau 
diese eine Aufgabe verwenden kannst. Die bessere Lösung wäre, deinen 
OCR-Wert irgendwo als Konstante zu definieren und bei jedem 
Compare-Interrupt das OCR um diese Konstante zu erhöhen. Funktioniert 
einwandfrei und du kannst den Timer auch für den zweiten 
Compare-Interrupt, sowie den Überlauf verwenden. Wenn du ihn sonst aber 
überhaupt nicht verwendest, ist das natürlich nicht unbedingt notwendig.

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.