Forum: Mikrocontroller und Digitale Elektronik Timer mal wieder - Hilfesuchend bei Überlaufberechnung


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Peter S. (petershaw)


Bewertung
-1 lesenswert
nicht lesenswert
Hi,

ich habe auf einem ATTiny2313 Board ein 20Mhz Tackt. Nun möchte ich eine 
exakte Sekunde mit Timer0 berechnen.

Nehme ich die Formel aus dem Tutorial, ergeben sich für

    sec = ((2 ^8) * 64) / 20000000;

Überläufe in der Sekunde. Will ich nun wissen wie viele das in der 
Sekunde sind, dann teile ich 1(sec) / die Überläufe.

So komme ich auf: 31250

Soweit so gut?

Nun stelle ich meinen Timer ein:

     // INIT TIMER
     // -----------------------------------------
     TCCR0A |= 1<<WGM01;
     // Timer 0, Prescaller /64; OVF-Interrupt
     TCCR0B |=  (0<<CS02) | (1<<CS01) | (1<<CS00);
     // Overflow Interrupt erlauben
     TIMSK |= (1<<OCIE0A);
     // Set MAX
     OCR0A |= 255;

und fange den interrupt:

ISR (TIMER0_COMPA_vect){
  tick++;
  if(tick == 31250){
      ++sekunde;
      tick = 0;
  }

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

Leider kommt es nicht zu einem Sekündlichen hochzählen. Meine 
Kontrolllampe bleibt an, sie sollte sekündlich blinken.

Kann mir jemand helfen?

: Verschoben durch Moderator
von A. S. (achs)


Bewertung
0 lesenswert
nicht lesenswert
Ich kenne Deinen µC nicht. Aber bei Vorteiler 64 und Zähler bis 256 
erwarte ich bei 20Mhz etwa 20.000.000/(256*64)=1220 Überläufe pro 
Sekunde. Je nach Architektur ggf. davon noch die Hälft oder ein Viertel.

Wenn es 31.000 pro Sekunde wären (30µs pro Interrupt), solltest Du dich 
fragen, ob es nicht viel zu viele Interrupts wären.

Zudem kannst Du probehalber einfach mal kleinere Werte nehmen (binäre 
oder logarithmische Suche. Also statt 31.000: 1000, danach 100 (10, 1) 
wenn immer noch statisch an, sonst halt mehr.

Viel Erfolg

: Bearbeitet durch User
von Wolfgang (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Peter S. schrieb:
> Meine Kontrolllampe bleibt an, sie sollte sekündlich blinken.

Deine Kontrolllampe wird auch nirgends im gezeigten Programm 
angesprochen. Warum sollte sie also ihren Zustand verändert - und wie 
soll dir hier jemand einen Tip geben, wenn keiner weiss, wie deine 
Kontrolllampe hard- und softwaremäßig mit deinem Programm zusammen 
hängt. Bist du dir sicher, dass dein µC überhaupt in die ISR rein 
springt?

von Peter (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hi,
Ja, mit anderen (Phantasie-)werten aus einem anderen Projekt klappt es, 
nur brauche ich hier exakte Sekunden.

von Peter S. (petershaw)


Bewertung
0 lesenswert
nicht lesenswert
Also dieser Code lässt so halbwegs im Sekunden-Takt an und ab schalten:


    TCCR0A |= 1<<WGM01;
    // Timer 0, Prescaller /1024; OVF-Interrupt
    TCCR0B |=  (1<<CS02) | (0<<CS01) | (1<<CS00);
    // Overflow Interrupt erlauben
    TIMSK |= (1<<OCIE0A);
    // Set MAX
    OCR0A |= 19 -1;

mit dem ISR:

ISR (TIMER0_COMPA_vect){
  millisekunden++;
  if(millisekunden == 1000)
  {
    sekunde++;
    millisekunden = 0;
    if(sekunde == 60)
    {
      minute++;
      sekunde = 0;
    }
    if(minute == 60)
    {
      stunde++;
      minute = 0;
    }
    if(stunde == 24)
    {
      stunde = 0;
    }
  }
}


aber wie ist denn die Formel, damit ich den so optimieren kann, dass ich 
genau auf einer Sekunde bin?

: Bearbeitet durch User
von Peter S. (petershaw)


Bewertung
0 lesenswert
nicht lesenswert
Ok, mit dem script kann ich mich nähern


    #!/usr/bin/perl

    $freq = 20000000;        # 20mhz
    $prescaler = 256;

    $countto = 255;          # overflow ISR
    for($i=$countto;$i>0;$i--){
  $ov = $freq / $prescaler;
  $every = ($ov / $i) / 1000;
  print "$every x/sec, $i\n";
    }

jetzt muss ich da nur noch die nächste 1 finden.
Aber irgendwie muss ich das doch auch ausrechnen können, oder? bzw 
jemand hier wird wissen, was die beste Einstellung ist ;)

Danke,
ps

von gfxjbv (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Die genaue Sekunde von P.Danneger, sozusagen DAS Standardwerk zum Thema:

Beitrag "Die genaue Sekunde / RTC"

gfxjbv

von Uwe S. (de0508)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

ich würde es etwas anders machen:
F_CPU = 20 *10^6
T0_MODE = 2 ' CTC Mode
T0_PRESCALER = 64
T0_PRELOAD = 250

T0_FREQUENCY = F_CPU /T0_PRESCALER /T0_PRELOAD
T0_FREQUENCY = = 20 *10^6 /64 /250 = 1250Hz

D.h. in Deiner ISR musst Du nun nur noch bis 1250 Zählen, um 1Hz zu 
erhalten.

: Bearbeitet durch User
von c-hater (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Uwe S. schrieb:
> Hallo Peter,
>
> ich würde es etwas anders machen:
> F_CPU = 20 *10^6
> T0_MODE = 2 ' CTC Mode
> T0_PRESCALER = 64
> T0_PRELOAD = 250
>
> T0_FREQUENCY = F_CPU /T0_PRESCALER /T0_PRELOAD
> T0_FREQUENCY = = 20 *10^6 /64 /250 = 1250Hz
>
> D.h. in Deiner ISR musst Du nun nur noch bis 1250 Zählen, um 1Hz zu
> erhalten.

Es ginge auch Prescaler 256 und Preload 125, dann müsste man bloss noch 
bis 625 zählen und die Interrupts würden nur halb so häufig auftreten.


Um mal darzustellen, wie man zu solchen Lösungen kommt: Das Zauberwort 
ist Primfaktorzerlegung.

20.000.000 = 2^8 * 5^7

Es spielen für die konkrete Aufgabe also nur Zahlen eine Rolle, die sich 
entweder als Potenz von 2 oder als Potenz von 5 oder als Produkt solcher 
Potenzen darstellen lassen. Die ganze Denkleistung besteht nun nur noch 
darin, diese Zahlen möglichst geschickt über die Teilerstufen zu 
verteilen und dabei deren jeweiligen Limitierungen einzuhalten. Deine 
Lösung wäre also:

(2^6) * (2^1 * 5^3) * (2^1 * 5^4)

und meine

(2^8) * (5^3) * (5^4)

In beiden Fällen finden sich alle Primfaktoren der ursprünglichen 
Zerlegung in genau der richtigen Menge wieder und es tauchen keine 
anderen auf. -> eine exakte Lösung für das Teilerproblem ist gefunden.

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]
  • [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.