Forum: Mikrocontroller und Digitale Elektronik Timer0 soll alle 460,33 ms ein Interrupt auslösen


von New D. (newproject)


Lesenswert?

Hallo,

Ich brauch mal einen Gedankenanstoss,

(Es muss Timer0 benutzt werden, so Aufgabenstellung.)
Undzwar soll alle 460,33ms ein Interrupt ausgelöst werden.
Mein Vorgehen:

Da der PIC mit 48 Mhz getaktet ist, wird der Timer0 mit einem Viertel 
unseres Taktes getaktet.
So die maximale Zählhöhe des Timer0 ist 2^16.
So also würden folgende Einstellungen des Timer0 lauten:
-16bit Counter
-Internal instruction cycle clock(Fosc/4)
-Prescaler: den müssen wir jetzt in abhängigkeit unseres Zählwertes etc 
einstellen.

Zählhöhe: 65535
Jetzt müssen wir ausrechnen wie lange ein Zählschritt brauchen muss 
damit wir bei einer Zählhöhe von 65535 eine Zeit von 460,33ms brauchen.
460,33 ms / 65535 = 7,02*10^(-6)
Also brauch er 7,02*10^(-6) pro Zähleinheit.

Ich weiss jetzt nicht so richtig weiter, bitte um Hilfe,

Vielen dank, Gruss

von Karl H. (kbuchegg)


Lesenswert?

New D. schrieb:

> Jetzt müssen wir ausrechnen wie lange ein Zählschritt brauchen muss
> damit wir bei einer Zählhöhe von 65535 eine Zeit von 460,33ms brauchen.
> 460,33 ms / 65535 = 7,02*10^(-6)
> Also brauch er 7,02*10^(-6) pro Zähleinheit.

Man kanns so rechnen. Ist aber meiner Meinung nach umständlich.

So ein µC hat ja nicht unendlich viele mögliche Prescaler.
Probier einen nach dem anderen durch, mit einer Zählweite von 65536. Bei 
welcher Zeit landest du dann jeweils?

Da das ganze nach Hausaufgabe aussieht und die angestrebte Zeit derart 
krumm ist, bin ich mir ziemlich sicher, dass sich die Rechnerei bei 
irgendeinem der verfügbaren Vorteiler genau ausgeht.

Das ganze ist auf dem Schweirigkeitsgrad von:
vom Baum fällt alle 5 Sekunden 1 Apfel.
Wenn ich mit dieser Fallrate 2 Stunden abstoppen müsste, wie viele Äpfel 
müssen dann runter fallen? Wenn ich mit den runterfallenden Äpfel 12 
Apfelkisten voll machen will, wieviele Äpfel müssen dann in jeweils 1 
Kiste?

Recht viel mehr steckt bei diesen ganzen Timerbetrachtungen nicht 
dahinter. Du klebst zu sehr an den Formeln ohne dir zu überlegen, was du 
eigentlich ausrechnest und warum.

von Karl H. (kbuchegg)


Lesenswert?

New D. schrieb:

> Jetzt müssen wir ausrechnen wie lange ein Zählschritt brauchen muss
> damit wir bei einer Zählhöhe von 65535 eine Zeit von 460,33ms brauchen.
> 460,33 ms / 65535 = 7,02*10^(-6)
> Also brauch er 7,02*10^(-6) pro Zähleinheit.

schön.

Bei einem Prescaler von 1 und dieser Einstellung ...

> Da der PIC mit 48 Mhz getaktet ist, wird der Timer0 mit
> einem Viertel unseres Taktes getaktet.
> So die maximale Zählhöhe des Timer0 ist 2^16.
> So also würden folgende Einstellungen des Timer0 lauten:
> -16bit Counter
> -Internal instruction cycle clock(Fosc/4)

... würde er wie lange für 1 Zählschritt brauchen?

Jetzt wissen wir, wie lange (bei einem Prescaler von 1) ein Zählschritt 
dauern würde. Wir wissen auch, wie lange er dauern soll. Daraus kann man 
jetzt ausrechnen um welchen Faktor runtergeteilt werden muss, damit aus 
dem 'Ist' das 'Soll' wird.

Aber man hat hier ekelhafte kleine Zahlen. Ich finde die Umkehrung 
einfacher zu rechnen: wie schnell wird der Timer getaktet. Durch welchen 
Prescaler wird geteilt? Wie weit wird damit gezählt? Das dauert daher 
wie lange?

Und das probier ich für die 4 oder 8 Prescaler, die es gibt durch. Beim 
ersten Prescaler (1) sieht man ohnehin, ob man mit dem Ergebnis weit 
daneben ist. Ein höherer Prescaler (zum Beispiel 8) verlängert die Zeit 
auf genau das x fache des Prescaler Wertes (also zum Beispiel das 
8-fache). Hab ich den ersten Wert bei einem Prescaler von 1, dann kann 
man mal im Kopf überschlagen, welcher Prescaler Wert wohl am nächsten 
drann ist. Kommt bei der Rechnung mit einem Prescaler von 1 ein Wert von 
1ms raus, und will ich eine Zeit von 64ms, dann wird ein Prescler von 64 
(falls verfügbar) genau das leisten.

Ist der notwendige Prescaler nicht verfügbar, dann nimmt man den nächst 
größeren verfügbaren und rechnet damit zurück, bis wie weit der Timer 
damit zählen muss, damit man die gewünschte Zeit kriegt. Wenn das 
bisherige sitzt, dann solltest du damit keine Schwierigkeiten haben, dir 
den Rechengang dazu selbst herzuleiten.

von 6a66 (Gast)


Lesenswert?

New D. schrieb:
> -Internal instruction cycle clock(Fosc/4)
> -Prescaler: den müssen wir jetzt in abhängigkeit unseres Zählwertes etc
> einstellen.

Richtiger Ansatz.
Falsche Ausführung.

Wenn Du mit 48 MHz taktest und einen FOSC/4 hast kommt am Zähler 12MHz 
an.
640,33ms / 0,0833us = 76.839.600. Das ist sehr viel Größer als 65535. 
Also musst Du den Vorteiler so einstellen dass damit ein Wert <65535 
herauskommt.
Da bietet sich ein Vorteiler von 2048 an (oder was auch immer der PIC 
hat). Damit kommst Du dann auf einen Zählerwert von 37519,.... Damit 
hast Du dann den Vorteiler udn den Zähler bestimmt. Der Interrupt kommt 
dann genau nach (2049*37519)/12 us = 6403242,67us

rgds

von Peter D. (peda)


Lesenswert?

Du berechnest einfach den Prescaler bei einem Timerwert von 65536.
Dann nimmst Du den nächst höheren erlaubten Prescalerwert (vermutlich 
128) und errechnest damit den passenden Timerwert.

von New D. (newproject)


Lesenswert?

Wow ich danke für die tolle Hilfe! Habe jetzt die möglichen 
Kombinationen durchgerchnet.

Maximaler prescaler beim pic18 timer0 ist 256.

Also nochmal:
1/12Mhz = 8,33 *10^(-8) s
Der Timer0 brauch 8,33*10^(-8) s pro Zählschritt.

Ein Overflow soll nach 460,33mS kommen.
Also hab ich mir folgendes überlegt:

8,33*10^(-8)s  Prescaler  Zählhöhe = 460,33mS
460,33ms/(8,33*10^(-8) s) = 5526170,468
Prescaler*Zählhöhe= 5526170,468

5526170,468 / 256(prescaler) = 21586,60339 Zählhöhe
=> Scheidet aus, zu niedrig

5526170,468 /128 = 43173,20 Zählhöhe
=> Scheidet aus, zu niedrig

5526170,468 / 64 = 86346,41 Zählhöhe
=> Scheidet aus, zu hoch

5526170,468 / 65536 = 84,32 Prescaler
=> Scheidet aus, gibts nicht.

Gehe ich das einfach komplett falsch an oder wieso komme ich nicht 
drauf?
Ich finde keinen passenden Prescaler

von 6a66 (Gast)


Lesenswert?

New D. schrieb:
> Ich finde keinen passenden Prescaler

Dann hast Du meine Antwort nicht sorgfältig gelesen.

rgds

von Karl H. (kbuchegg)


Lesenswert?

New D. schrieb:

> Gehe ich das einfach komplett falsch an oder wieso komme ich nicht
> drauf?
> Ich finde keinen passenden Prescaler

Das kann natürlich sein, dass es sich mit keinem Prescaler ausgeht.
Der andere Wert, an dem du drehen kannst, dass sind die 65536. Dann darf 
halt der Timer nicht durchlaufen, sondern muss bereits bei einem 
Zählerstand vorher den Interrupt auslösen und wieder bei 0 anfangen.

Dieser ominöse Zählerstand kann logischerweise nur kleiner als 65535 
sein. Also nimmst du einen Prescaler, bei dem du knapp über der Zielzeit 
bist und rechnest zurück, wie weit der Timer bei diesem Prescaler zählen 
darf, damit du die Zielzeit erhälst. Wenn der Timer nicht so weit zählt, 
wird dieser 'Endwert' etwas schneller erreicht - die Zeit dafür sinkt 
also ein wenig.

von New D. (newproject)


Lesenswert?

Aber mein Timer0 darf doch nur bis entweder 255 oder 65535 zählen. Also 
kann ich doch gar nicht einen beliebigen Zählwert ausrechnen, denn der 
löst den Interrupt doch nur bei entweder +255 oder + 65535 aus. ?

von 6a66 (Gast)


Lesenswert?

New D. schrieb:
> Ein Overflow soll nach 460,33mS kommen.

Korrekt solltest Du sagen:
Ein Interrupt soll nach 460,33mms kommen, der Timer muss dazu noch nicht 
am Ende sein. Er kann prinzipiell auch bereits bei der Hälfte oder jedem 
anderen Wert einen Interrupt erzeugen oder Überrollen (auf 0 
zurückgesetzt werden).

rgds

New D. schrieb:
> 460,33ms/(8,33*10^(-8) s) = 5526170,468

Genau gesagt: 460330*12 = 5523960

6a66 schrieb:
> 640,33ms / 0,0833us = 76.839.600
Da habe ich mich gründlich verrechnet.

So und jetzt suchts Du den Prescalerwert mit demm du auf einen Wert 
kommst bei dem der Timer nach 640,33ms noch kleiner 0xffff ist.

rgds

von Klaus (Gast)


Lesenswert?

New D. schrieb:
> Aber mein Timer0 darf doch nur bis entweder 255 oder 65535 zählen. Also
> kann ich doch gar nicht einen beliebigen Zählwert ausrechnen, denn der
> löst den Interrupt doch nur bei entweder +255 oder + 65535 aus. ?

Nein, nein. :-) Mit einem gewissen Vorbehalt, denn ich kenne die PICs 
nicht gut, kann man einen Interrupt bei einem beliebigen Zählerstand 
auslösen lassen. Da ist nochmal Datenblattstudium angesagt,

von Karl H. (kbuchegg)


Lesenswert?

Abgesehen dvon.
rechne nicht so viel rum. Du handelst dir da eine Menge Rundungsfehler 
ein.

Wenn ich rechne:
1
12000000 * 0.46033 / 128 = 43155

dann lande ich bei einem Vorteiler von 128 dabei, dass ich den Timer bis 
43155 laufen lassen möchte. Bei 12Mhz Timertakt.

Du hingegen kriegst mit deinen vielen Umrechnungen in Zeiten raus
1
5526170,468 /128 = 43173,20 Zählhöhe

zwischen 43173 und 43155 ist dann schon ein kleiner Unterschied.
(Ursache ist, dass 1/12 eben nicht 8,33 *10^(-8) s ist, sondern du da 
ein paar Kommastellen unterschlagen hast. Mal angenommen die 12Mhz sind 
absolut genau, dann würdest du bei 43173 eine Zeit von 460.512ms 
erhalten und nicht 460.33ms. Abgesehen davon tippt sich 12000000 viel 
leichter in den Taschenrechner als dieses ganze Potenzzeugs
1
12000000 / 128 / 43155 = 2.17irgendwas. Davon der Kehrwert = 0.46032 Sekunden)

von Chris (Gast)


Lesenswert?

Nein, der Timer löst beim erreichen des Compare-Wertes aus...

von New D. (newproject)


Angehängte Dateien:

Lesenswert?

Ich glaube hier ist ein Missverständnis.
Mit Timer2 kann man nach einem beliebigen Wert einen Interrupt auslösen, 
aber nicht bei TIMER0. Da gibt es kein Compare Wert

von Klaus (Gast)


Lesenswert?

New D. schrieb:
> Ich glaube hier ist ein Missverständnis.
> Mit Timer2 kann man nach einem beliebigen Wert einen Interrupt auslösen,
> aber nicht bei TIMER0. Da gibt es kein Compare Wert

Dann hätte ich doch gerne mal den präzisen Aufgabentext und den Typ des 
PICs gewusst.

Möglich ist es, aber dann hat entweder der Lehrer keine Ahnung oder der, 
der dieses Bildchen gemacht hat oder irgendeiner lockt Euch in eine 
kleine Falle.

von foo (Gast)


Lesenswert?

Du kannst aber TMR0 setzen, sodass er weniger lange bis zum Overflow 
braucht. Und das machst du jedes Mal wenn der Interrupt ausgelöst wird. 
Somit lässt du ihn nur von (65535-x) bis 65535 laufen.

von Klaus (Gast)


Lesenswert?

Ausserdem hast Du die ganze Zeit was einem maximalen Zählerstand von 
2^16 erzählt. Wo kam denn diese Zahl her. (Abgesehen davon, dass sie 
2^16 - 1 wäre).

von Falk B. (falk)


Lesenswert?

@ Karl Heinz (kbuchegg) (Moderator)

>Wenn ich rechne:

>12000000 * 0.46033 / 128 = 43155

Und ich behaupte mal wieder, dass kein zurechnungsfähiger Mensch 
explizit einen Timerinterrupt alle 460,33ms haben will. "Bestenfalls" 
ergibt sich so eine Takt aus ungünstigem Quarztakt und Teilern.

von Karl H. (kbuchegg)


Lesenswert?

Falk B. schrieb:
> @ Karl Heinz (kbuchegg) (Moderator)
>
>>Wenn ich rechne:
>
>>12000000 * 0.46033 / 128 = 43155
>
> Und ich behaupte mal wieder, dass kein zurechnungsfähiger Mensch
> explizit einen Timerinterrupt alle 460,33ms haben will.


Ich denke, es handelt sich um eine Schulaufgabe

von Klaus (Gast)


Lesenswert?

Falk B. schrieb:
> @ Karl Heinz (kbuchegg) (Moderator)
>
>>Wenn ich rechne:
>
>>12000000 * 0.46033 / 128 = 43155
>
> Und ich behaupte mal wieder, dass kein zurechnungsfähiger Mensch
> explizit ...

Guck mal in Wikipedia. Du wirst weder unter "Lehrer" was von 
Zurechnungsfähigkeit noch unter "Zurechnungsfähigkeit" was von Lehrern 
lesen. :-)

von Falk B. (falk)


Lesenswert?

@ Karl Heinz (kbuchegg) (Moderator)

>> Und ich behaupte mal wieder, dass kein zurechnungsfähiger Mensch
>> explizit einen Timerinterrupt alle 460,33ms haben will.

>Ich denke, es handelt sich um eine Schulaufgabe

Nicht für das Leben, nein, für die Schule lernen wir . . .

von New D. (newproject)


Lesenswert?

foo schrieb:
> Du kannst aber TMR0 setzen, sodass er weniger lange bis zum
> Overflow
> braucht. Und das machst du jedes Mal wenn der Interrupt ausgelöst wird.
> Somit lässt du ihn nur von (65535-x) bis 65535 laufen.

Wie meinst du das?

von foo (Gast)


Lesenswert?

New D. schrieb:
> Wie meinst du das?

Du setzt am Anfang TMR0 auf (65535-x). Dann lässt du ihn laufen.

x Timerzyklen später wird es einen Overflow geben und dein Interrupt 
wird ausgelöst. Im Handler setzt du TMR0 wieder auf (65535-x) und machst 
dann den Rest (was auch immer alle 460,xx ms passieren soll).

Es dauert nun wieder x Timerzyklen bis zum nächsten Overflow... und so 
weiter.

Wenn du eben auf Timer0 festgelegt bist und dieser kein Compare Register 
hat, muss man sich das eben zusammenbasteln.

von Klaus (Gast)


Lesenswert?

Das ist natürlich auch eine Möglichkeit. Allerdings nicht trivial, denn 
die Interrupt-Frequenz ist nicht in Faktoren zerlegbar, die einem der 
Prescaler entspricht. Dann wäre noch die Frage, ob das das durch die 
Zyklen für die Befehle im Interrupt und das Neuladen des Timers etc. 
irgendwie gerade hinkommt oder wie genau die 460,33ms sein sollen.

Aber das sollte ja im Aufgabentext stehen.

von foo (Gast)


Lesenswert?

Klaus schrieb:
> Das ist natürlich auch eine Möglichkeit. Allerdings nicht trivial,
> denn
> die Interrupt-Frequenz ist nicht in Faktoren zerlegbar, die einem der
> Prescaler entspricht.

Korrekt. Demnach ist die Aufgabe streng genommen unlösbar. Es gibt einen 
Prescaler, aber die Zahl der Takte bis zum nächsten Reset hat über 16 
Bit. Man könnte zwar alle 460,33ms bestimmten Code ausführen (man zählt 
im Handler auch die Zahl der Overflows mit) aber der Timer würde 
Interrupts häufiger als alle 460,33ms feuern -> Aufgabe verfehlt.

> wie genau die 460,33ms sein sollen.
>
> Aber das sollte ja im Aufgabentext stehen.

Ich wage zu behaupten, dass es nicht drin steht. Zumindestens kenne ich 
solche Aufgaben mit krummen Zahlen, die "rein zufällig" zu einem runden 
Ergebnis führen, nicht anders. Ich würde in die Antwort mit 
reinschreiben, dass es einen vernachlässigbar kleinen Fehler von 0.67 
Mikrosekunden gibt, der aber unvermeidbar ist, weil kein kleinerer 
Prescaler gewählt werden kann.

von Klaus (Gast)


Lesenswert?

Irgendwie komisch. Normalerweise, d.h. bei "zurechnungsfähigen Lehrern" 
(TM) hat das einen Grund, wenn eine Aufgabe nicht trivial zu lösen ist.

Didaktisch fängt man doch mit einfachen Aufgaben an und wenn die gelöst 
werden können, lehrt man weitere Gesichtspunkte und fügt den Aufgaben 
diese hinzu. Entweder, dass die einfachen Aufgaben genauer betrachtet 
nicht exakt gelöst wurden oder die Vorgaben so gemacht wurden, dass die 
einfachen Lösungen auch exakt waren.

Ich war dann doch mal fleissig und habe das in den Taschenrechner 
eingetippt und komme darauf, dass selbst wenn der Timer 16 Bit hätte, 
noch ein Fehler von rund 1us bleibt. Praktisch oft nicht relevant, aber 
unsere Videobastler hier die mit einem AVR ein FBas-Signal erzeugen, 
würden vielleicht die Hände über dem Kopf zusammenschlagen.

Die Frage stellt sich also an welchem Punkt im Unterricht diese Aufgabe 
gestellt wurde. Wenn der TO nun so fragt, wie er es tat, hat er nicht 
mal mit einfachen Fällen Erfahrung. Geschweige denn mit der Einbeziehung 
der Zykluszeiten für das Timer-Reload etcpp.

Das ist mysteriös und lässt als plausible Vermutung zu, dass dem 
Aufgabensteller die Zahl auf dem Klo eingefallen ist.

von Ottmar K. (wil1)


Lesenswert?

New D. schrieb:
> Hallo,
>
> Ich brauch mal einen Gedankenanstoss,
>
> (Es muss Timer0 benutzt werden, so Aufgabenstellung.)
> Undzwar soll alle 460,33ms ein Interrupt ausgelöst werden.


Die "besseren PICs" z.B.18F2450 haben 2 TMR0-Modes:

·  8Bit bzw. 16Bit umschaltbar im  Register T0CON.
·  Interrupt wird ausgelöst durch TMR0-overflow
·  Der Prescaler ist auf max. 256 beschränkt.

Damit wäre das Problem so zu lösen:

fosc/4 = 48.000.000Hz : 4    = 12.000.000Hz (->Arbeitszyklen)
Interrupt-Intervall 460,33ms = 460330 Arbeitszyklen
TMR0 Zählbereich 0-2^16      = 0-65535 = 65536 clocks
Prescaler(1)                 = 460330 : 65536 = 8 (aufgerundet)
Prescaler(2) = 12.000.000 : 460330 = 27 (aufgerundet)
Prescaler                          = 27*8 = 216
nächster größerer verfügbarer Wert = 256
;----------------------------------------

12.000.000Hz  :  256 = 46875 TMR0-clocks (passt in Zählbereich)

Preset TMR0  65536-46875 = 18661 = 48E5h

1. Timer0 Clock Source Select - fosc/4 aktivieren
2. TMR0-overflow Interrupt aktivieren (INTCON,TMR0IE=1)
3. Preset in der Interrupt-Service-Routine (ISR) ausführen.

zum Beispiel TMR0-Preset in MPLAB-Assembler:

movlw    0x48
movwf    TMR0H  ;H-Byte
movlw     0xE5
movwf     TMR0L  ;LByte

Ab sofort, wenn TMR0 überläuft, wird automatisch das Flag INTCON,T0IF 
gesetzt und ein Interrupt ausgelöst. In der ISR wird TMR0 stets auf den 
richtigen Presetwert gesetzt.

mfG Ottmar

von Dieter F. (Gast)


Lesenswert?

Ottmar K. schrieb:
> 12.000.000Hz  :  256 = 46875 TMR0-clocks (passt in Zählbereich)

Yep, damit zählt er genau 1 Sekunde ... aber was ist mit den 460,33 mS ?

von Dieter F. (Gast)


Lesenswert?

Ich habe keine Ahnung von PIC - aber wenn es unbedingt so sein soll 
würde ich mir einen passenden Quarz suchen :-)

von foo (Gast)


Lesenswert?

12MHz/256 * 460,33ms = 21577,969 also für den geringsten Fehler 21578.

Wenn der auch 128 als Prescaler haben sollte, nimmt man den und rechnet 
ähnlich.

Wenn mans ganz genau haben will, rechnet man vorher noch die Takte 
runter, die man braucht, um TMR0 neu zu schreiben, aber da müsste ein 
PIC-Assemblerprofi ran.

von Dieter F. (Gast)


Lesenswert?

foo schrieb:
> Wenn mans ganz genau haben will, rechnet man vorher noch die Takte
> runter, die man braucht, um TMR0 neu zu schreiben, aber da müsste ein
> PIC-Assemblerprofi ran.

Wenn ich die Aufgabe wörtlich nehme, soll der Interrupt (und damit die 
ISR) alle 460,33 mS ausgelöst werden - egal, wie lange die ISR etc 
dauert. Aufgabe ist das exakte Intervall des Auslösers, nicht die 
Abarbeitung ...

Also einmal einstellen und dann bis St. Nimmerlein laufen lassen.

Das geht bei dem krummen Wert mit dem angegebenen Takt nicht genau. 
Entweder man rundet leicht (wie Karl-Heinz) oder man passt den Takt an.

von Peter D. (peda)


Lesenswert?

1
12MHz * 460,33ms = 5523960
2
3
5523960 / 655356 = 84,3
4
-> Prescaler = 128
5
6
5523960 / 128 + 0.5 = 43156
7
8
Kontrolle:
9
43156 * 128 / 12MHz = 460,3307ms

Falls nun der Timer keinen Autoreload- oder Clear_on_Compare-Mode hat, 
kann man den Timer einfach in SW neu setzen.
Z.B. im Überlaufinterrupt setzt man ihn auf -43156.
Dazu hat man den Prescaler lang Zeit, d.h. 128 Zyklen.
Ist also bequem in C zu schaffen, Assembler ist unnötig.

von foo (Gast)


Lesenswert?

Dieter F. schrieb:
> Wenn ich die Aufgabe wörtlich nehme, soll der Interrupt (und damit die
> ISR) alle 460,33 mS ausgelöst werden - egal, wie lange die ISR etc
> dauert. Aufgabe ist das exakte Intervall des Auslösers, nicht die
> Abarbeitung ...

Das kriegste schon exakt hin, wenn TMR0 neu setzen das erste ist, was du 
in der ISR machst. Wie lange der Rest der ISR braucht, ist dann egal - 
der Timer zählt währenddessen schonmal weiter

Man muss dazu sagen, dass ein anderer Interrupt aktiv sein könnte, 
während der Overflow-Interrupt kommt, d.h. TMR0 wird verspätet 
überschrieben - damit dauerts dann aber auch länger bis zum nächsten 
Overflow. Dem kann man vorbeugen, indem man den Wert zu TMR0 dazuaddiert 
statt ihn zu ersetzen.

> Also einmal einstellen und dann bis St. Nimmerlein laufen lassen.

Mir wäre das auch deutlich lieber, aber Timer0 hat nun mal keinen 
Compare Interrupt, wenn ich das richtig sehe. Die anderen Timer schon. 
Aber die sollen laut Aufgabe eben nicht verwendet werden.

Ich würde wetten, dass das deshalb Vorgabe ist, damit man eben diese 
(oder eine andere) Bastellösung verwenden muss. Mit Compare Register 
wäre es ja nun wirklich zu einfach.

von Peter D. (peda)


Lesenswert?

P.S.:
Hab grad das Bildchen gesehen, der Timer ist ja nur 8 Bit.
Ist aber kein Beinbruch, dann zerlegen wir einfach weiter:
1
5523960 / 256 + 0,5 = 21578
2
21578 = 84 * 256 + 74
D.h. wir nehmen noch ne Variable, die bis 84 zählt und nur dann wird der 
Timer auf -74 geladen, die Variable auf 0 gesetzt und das 460,33ms Ding 
gemacht.

von Ottmar K. (wil1)


Lesenswert?

Dieter F. schrieb:
> Ottmar K. schrieb:
>> 12.000.000Hz  :  256 = 46875 TMR0-clocks (passt in Zählbereich)
>
> Yep, damit zählt er genau 1 Sekunde ... aber was ist mit den 460,33 mS ?

Habe gerade noch mal in den Thread reingeschaut:

OK- hab mich wohl beim Schreiben selbst überholt :-) und dabei den 
wichtigsten Punkt versäumt:

Da so der Preset für 1 Sekunde ISR-Intervall feststeht, braucht nur noch 
durch den Kehrwert der Intervallzeit in Sekunden (ergibt Hz), geteilt zu 
werden und man erhält den Presetwert für 0,46033s ISR-Intervall so:

 46875 clocks / (1 / 0,46033s) = 21577 clocks (da abgerundet!)

Gegenprobe: (1/0.46033s)   256  21577 = 1199461Hz

Die fehlenden 539 clocks müssten dann durch eine genau bemessene 
Schleife
in der ISR hinzugefügt werden (inklusive des dort vorzunehmenden Setzen 
des Presetwertes)

Fazit:

Als Formel ergibt sich die Anzahl der für das ISR-Intervall 
erforderlichen TMR0-Clocks so:

Arbeitszyklen / (1/t) / Prescaler  = TMR0-Clocks
fosc/4           t(s)   2....256

Der Presetwert für TMR0 (16Bit) = 2^16 - TMR0-Clocks
im vorliegenden Falle wäre Preset dann:
                65536 - 21577 = 43959 = ABB7h

@Dieter F- Danke für den Hinweis auf meine Leichtfertigkeit!

mfG Ottmar

P.S.: Selbst vor die Aufgabe gestellt, würde auch ich den 
Compare-Interrupt der vorgenannten aufwendigeren Lösung vorziehen.

von New D. (newproject)


Lesenswert?

Hallo,

Ich danke euch allen, die Lösung war, wie verschiedene schon angedeutet 
hatten, dem Timer0 in der Interrupt Service Routine einen festen 
Startwert zu übergeben.

Gruss

von Dieter F. (Gast)


Lesenswert?

New D. schrieb:
> Ich danke euch allen, die Lösung war, wie verschiedene schon angedeutet
> hatten, dem Timer0 in der Interrupt Service Routine einen festen
> Startwert zu übergeben.

Welcher Startwert war es denn? Und kommt man damit genau auf die 
geforderten 460,33 mS?

von New D. (newproject)


Lesenswert?

War ein Startwert von 43870 ;)

von Karl H. (kbuchegg)


Lesenswert?

New D. schrieb:
> War ein Startwert von 43870 ;)

Das ist nicht richtig.
Du hast ja schon wieder vorzeitig duchdividiert und dabei Kommastellen 
verloren!

Dein benutzter Vorteiler war offenbar 256
1
12000000 / 256 = 46875
so weit würde der Timer in 1 Sekunde zählen.
Wir brauchen aber nur 0.46033s. Daher
1
46875 * 0.46033 = 21577
Der Timer muss also 21577 Zählschritte machen, danach sind 0.46033 
Sekunden vergangen.
Damit der Timer 21577 Zählschritte macht, bis er bei 65536 angelangt ist 
(und damit den Overflow auslöst), muss er bei
1
65536 - 21577 = 43959

gestartet werden.

Vergiss endlich dieses Rumrechnen mit 'wie lange dauert ein Zählzyklus'.

Edit:
Die 21577 könnte man auch als 21578 ansehen, dann das Rechenergebnis ist 
21577.9.
Aber auch das rettet deine Abweichung vom Ergebnis nicht mehr. 43870 ist 
weit von 43959 entfernt. Da geht es nicht mehr um einen Fehler +- 1

von New D. (newproject)


Lesenswert?

Ja hast natürlich recht, hab die Nachkommastellen nicht mehr beachtet.

Vielen dank für die tolle Hilfe!
Gruss

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.