Forum: Mikrocontroller und Digitale Elektronik ATmega16 - 16bit Counter mit definierter "Auflösung"


von Florian R. (Firma: TU Wien) (frist)


Lesenswert?

Hallo,
ich versuch eigentlich eine ganz einfache Uhr zu programmieren, aber
ich kommt mit dem 16bit Couter nicht klar.

Also ich möchte, dass der Zähler von 0 aufwärts bis zu einer
definierten Obergrenze, dann einen Interrupt auslöst und wieder auf 0
springt.

Wenn ich das Datenblatt (Seite 87ff) recht verstehe sollte das gehen,
bei mir klapst aber nicht, ich hab wohl irgendwas vergessen:

// interrupt handler
SIGNAL (SIG_OUTPUT_COMPARE1A) {
  TCNT1=0;                // das wär ich gern los
  PORTD ^= (1<<PD5);
{

// init
void init (void) {
    OCR1A = 1000;              // counter top
    TIMSK |= (1<<OCIE1A);      // enable compare interrupt
    TCCR1B |= (1<<CS10 | 0<<CS11 | 1<<CS12);   // set prescale
    TCNT1=0;                   //reset counter
}

Das Ganze funktioniert so wie's soll, aber leider steht da im
Interrupthandler diese TCNT1=0 das passt mir nicht, und eigentlich
sollte das in Hardware gehen, nur wie?

Grüße
Flo

von chri (Gast)


Lesenswert?

Du suchst den CTC Mode (Clear timer on compare match), ich glaub das bit
heißt WGMxx ( oder CTC).. steht aber auch im Datenblatt.. schau nochmal
nach.
 Chris

von Florian R. (Firma: TU Wien) (frist)


Lesenswert?

Hallo,

> Du suchst den CTC Mode (Clear timer on compare match),

Ja, genau. Laut Datenblatt gibt's den...

> ich glaub das bit heißt WGMxx ( oder CTC)..

Stimmt, es gibt ein Bit WGM12 im TCCR1A Register, das den CTC Mode
aktivieren sollte, das bringt aber nix - keine Veränderung, egal ob ich
das Bit setze oder nicht.

Da muss noch ein Trick sein.

Grüße
Flo

von Florian R. (Firma: TU Wien) (frist)


Lesenswert?

Hallo,
ich hab's gefunden, blöder Fehler:

Also, man muss das Bit WGM12 im TCCR1_B_ Register setzen. Blöderweise
ist WGM12 im Datenblatt aber im Abschnitt für TCCR1A erläutert...

/ interrupt handler
SIGNAL (SIG_OUTPUT_COMPARE1A) {
  PORTD ^= (1<<PD5);
{

// init
void init (void) {
    OCR1A = 1000;              // counter top
    TIMSK |= (1<<OCIE1A);      // enable compare interrupt
    TCCR1B |= (1<<CS10 | 0<<CS11 | 1<<CS12 | 1<<WGM12);   // set
prescale to 1024 and enabel CTC mode
    TCNT1=0;                   //reset counter
}

So funktionierts.

Grüße
Flo

von Hannes L. (hannes)


Lesenswert?

Durch Verwenden des CTC-Mode verzichtet man aber auf die anderen netten
Features des Timers...
Weitere Erklärungen siehe:
http://www.mikrocontroller.net/forum/read-1-233282.html#233728

...

von Florian R. (Firma: TU Wien) (frist)


Lesenswert?

Hallo HanneS

> Durch Verwenden des CTC-Mode verzichtet man aber auf die anderen
> nette Features des Timers...
> Weitere Erklärungen siehe:
> http://www.mikrocontroller.net/forum/read-1-233282.html#233728

Interessanter Thread, danke.

Ich hab die CTC Lösung implementiert, weil ich sie für besser gehalten
hab, als die den Timer im Timerinterrupt per Software zu resetten, so
wird nämlich die Zeit zwischen dem Interruptrequest und dem Neusetzen
des Zählers nicht berücksichtigt. Da ist CTC schon eine Verbesserung.

Allerdings ist die von Dir beschriebene Methode noch viel besser und da
kann auch keine "Zeit verbohren gehen". Werde ich morgen gleich mal
implementieren. Da hab ich das Timerkapitel im Datenblatt dreimal
gelesen aber das Potential der Output Compare Interupts überhaupt nicht
verstanden.

Noch mal danke für Deinen Hinweis,
Grüße
Flo

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
Noch kein Account? Hier anmelden.