mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATmega168 Timer Compare Interrupt Zeitzählung


Autor: tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo.

Ich bin zurzeit dabei mich in die AVR Welt einzuarbeiten. Dabei bin ich 
auf den Artikel 
http://www.mikrocontroller.net/articles/AVR-GCC-Tu... 
gestoßen. Ich habe das ganze für de n ATMega168 angepasst aud gebe die 
entsprechenden Werte (ms, s, m und h) auf einem 20x4 Display aus. Es 
sieht subjektiv betrachtet soweit ok aus. Trotzdem hänge ich an einem 
Gedanken/Problem fest. Bei mir ist auf dem Board ein 16MHz Quarz drauf. 
Über den Prescaler von 64 bekommt der Timer 250.000 mal pro Sekunde 
einen Impuls. Daher soll nach 250 Impulsen ein Compare Interrupt 
ausgelöst werden (Zeile: OCR0A = 250;). D.h. jede ms gibts einen Compare 
Int und ein entsprechender Counter kann incrementiert werden. Bedeutet 
das jetzt, dass der Timer beim 250 Impuls einen Int auslöst, der 
MilliSek-Counter wird erhöht, dann Zählt der Timer weiter bis 255 und 
dann fängt er wieder bei 0 an, zählt wieder bis 255 und löst vorher bei 
250 wieder einen Compare Int aus. Das würde ja bedeuten, dass sich ein 
Fehler von 5 Timer-Taken einschleicht, oder? Müsste nicht beim Auslösen 
den Compare Int das Zählregister des Timers auf 0 zurück gesetzt werden?

Ich hatte das testweise mal mit einem Prescaler von 256 probiert und 
OCR0A = 63. Sah rein subjektiv genauso gut aus(Counter für Sek wurde im 
Display etwa im SekundenTakt aktualisiert), obwohl hier der Fehler viel 
größer sein müsste, wenn der Timer bis 255 wiederzählt und dann bei 0 
beginnt und wieder bei 63 einen Comp Int auslöst. Hab ich da irgendetwas 
übersehen?

Auszug auf meinem Code:
// Timer-Compare Test-Funktion
void start_timer_compare()
{
    char Buffer[20];

    /*   Timer0 ( 8 bit ) konfigurieren */
    TCCR0A |= (1<<WGM01);
    TCCR0B |= ((1<<CS01)|(1<<CS00));
    // 1; Timer0 Vorteiler: 64 -> bei 16 MHz: 
    // 16.000.000 / 64 = 250000 Mal pro Sek gibts einen Takt an den Timer
    
    OCR0A = 250;
    // Timer0 soll bei 250 einen Output Compare Interrupt auslösen ->
    // 250.000 / 250 = 1000 mal pro Sek gibts einen Interrupt

    //Compare Interrupt aktivieren
    TIMSK0 |= (1<<OCIE0A);

    //Globale Interrupts aktivieren
    sei();

    while(1)
    {
        // DisplayAsgabe
        // eine virtel Sekunde warten bis zur nächsten Anzeige
        _delay_ms( 250 );
    }
  
    return;
}

// Der Compare Interrupt Handler
// Wird aufgerufen wenn OCR0B = 250
ISR (TIMER0_COMPA_vect)
{
    millisekunden++;

    if( millisekunden == 1000 )
    {
        sekunde++;
        millisekunden = 0;

        if(sekunde == 60)
        {
            minute++;
            sekunde = 0;
        }

        if(minute == 60)
        {
            stunde++;
            minute = 0;
        }
    }
}

Autor: Captain Subtext (captainsubtext)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schön, dass Du alleine schon so weit gekommen bist und Dir auch über 
dieses kleine Detail Gedanken gemacht hast!

Zur Frage:
Der Timer läuft durch deine Initialisierung im CTC-Modus (Clear Timer on 
Compare Match  Modus).
Dort wird der Timer mit dem Auslösen des Interrupts zurückgesetzt.

Näheres erfährst Du im Datenblatt* des AtMega168, Seite 94, Abschnitt 
14.7.2!
Darauf hättest Du aber auch selbst kommen können ;)

*http://www.atmel.com/dyn/resources/prod_documents/...

Autor: Tom M. (tomm) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
tom schrieb:
> Das würde ja bedeuten, dass sich ein
> Fehler von 5 Timer-Taken einschleicht, oder? Müsste nicht beim Auslösen
> den Compare Int das Zählregister des Timers auf 0 zurück gesetzt werden?

Ja, das geschieht automagisch, weil du den CTC Modus konfiguriert hast:
>     TCCR0A |= (1<<WGM01);

Schau mal ins Datenblatt zum atmega48/88/168/328, da steht nämlich:

12.7.2 Clear Timer on Compare Match (CTC) Mode
In Clear Timer on Compare or CTC mode (WGM02:0 = 2), the OCR0A Register 
is used to manipulate the counter resolution. In CTC mode the counter is 
cleared to zero when the counter value (TCNT0) matches the OCR0A. The 
OCR0A defines the top value for the counter, hence also its resolution.


Gute n8 :)

Autor: tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo und vielen Dank.

Ich habs wirklich übersehen. Diese Sucherei im Datenblatt, was ich 
wirklich die ganze Zeit offen gehabt hab, hat mich ganz wuschig gemacht. 
Ich muss mich erst an die vielen Registernamen gewöhnen, dann verliere 
ich wohl auch nicht mehr den Blick für wesentliche.

Frohe Wihnachten

Gruß Tom

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.