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
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
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?
Hi, Ja, mit anderen (Phantasie-)werten aus einem anderen Projekt klappt es, nur brauche ich hier exakte Sekunden.
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
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
Die genaue Sekunde von P.Danneger, sozusagen DAS Standardwerk zum Thema: Beitrag "Die genaue Sekunde / RTC" gfxjbv
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
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.