Forum: Mikrocontroller und Digitale Elektronik [pic] TMR0 initialisieren


von Thomas M. (xt-fahrer)


Lesenswert?

Hallöchen,
mein Prog für den 16f84a macht nicht so ganz das, was es soll. Ich nutze 
die ISR für einen TMR0-Interrupt. Dabei soll TMR0 mit einem Wert geladen 
werden, sodaß alle 100µs der Interrupt ausgelöst wird. Ich habe mir vor 
längerer Zeit mal die Formel dafür hergeleitet, aber meine Schmierzettel 
für diese Berechnung sind weg :-( Sagt mir doch bitte, ob das korrkt 
ist:

TMR0_INIT = 256 - (looptime*fosz)/(prescaler^2)

Bei 20 MHz Oszillatorfrequenz und 100µs looptime und Prescaler 1:4 komme 
ich auf 131 bei o.g. Konfiguration. Stimmt das?

Gruß
T.

von Stefan (Gast)


Lesenswert?

Sieht gut aus

von Michael H. (morph1)


Lesenswert?

sicher das du fosc und nicht fcyc verwenden solltest? hab die 18er schon 
lange nimma verwendet, aber die rennen intern mit 1/4 vom externen takt

von Thomas M. (xt-fahrer)


Lesenswert?

Könnte es sein, daß ich die Viertel vom Oszillatortakt und die Viertel 
vom Prescaler einfach zusammengeschmissen habe?

Gruß
T.

von Chris (Gast)


Lesenswert?

2 Takte für die Syncronisierung des Timers nach dem write + Sprung zum 
ISR + Zeit in der ISR für das Neuladen musst du natürlich auch bedenken, 
sonst läuft dir der Interrupt falsch.

von André H. (andrekr)


Lesenswert?

Die Timer beziehen sich auf die Instruction Cycle Clock. Bei 20 MHz 
Oszillatorfrequenz hat die 5 MHz. Mit Prescaler 4 also 1,25 MHz oder 800 
ns pro Timertakt. Bei einem 8-Bit-Timer also 204,8 µs zwischen den 
Überläufen.

In welchem Zusammenhang das zu deinem TMR0_INIT steht, kann ich nicht 
sagen, weil ich nicht weiß, was TMR0_INIT ist.

von Stefan (Gast)


Lesenswert?

Und bei einem Timer Preload von 131 hat er dann
100µs. Also stimmt seine Rechnung.

von Chris (Gast)


Lesenswert?

Ja, aber die 2 Takte zur Syncronisation + 2 Takte für den ISR Sprung +
ca 8 Takte für die Rettung von Register und Timer initialisieren machen
dann aus 100uS ca 110uS.

von Thomas M. (xt-fahrer)


Lesenswert?

Nicht ganz, weil ich als erstes in der ISR (nach dem Registerretten) 
TMR0 wieder lade, sodaß er bereits in der ISR wieder hochzählt

Gruß
T.

p.s.: TMR0_INIT ist ein #define von mir, damit ich die Werte im 
Programmcode nicht suchen muß

von Thomas M. (xt-fahrer)


Lesenswert?

Ok, mir noch eine andere Idee gekommen. Wenn ich die ISR-Anweisungen ins 
Hauptprogramm integriere, etwa so:
[avrasm]
mnloop  movf TMR0,W
        btfss STATUS,Z
        goto mnloop

        movlw TMR0_INIT
        movwf TMR0
        .
        .
        . (restliche ISR-Anweisungen)
[\avrasm]
dann würde das Hauptprogramm, wenn es am Ende wieder zur mainloop 
springt, erstmal den movf und btfss abarbeiten, bis TMR0 mit dem 
Preload-Wert auf Null überläuft. Dann gäbe es doch keine Probleme mit 
überschüssigen Anweisungen zur Registerrettung und Sprünge in die ISR.
Oder?

Gruß
T.

von Chris (Gast)


Lesenswert?

Hier ein funktionierender Code, aber am besten ist es
#define uS *5                     ; vereinfacht

isr:
  movwf   w_temp            ; save off current W register contents
  movf  STATUS,w          ; move status register into W register
        clrf    STATUS            ; Bank switching and bit clearing.
  movwf  status_temp       ; save off contents of STATUS register
        movf    PCLATH,w          ; save PCLATH
        movwf   pclath_temp
        clrf    PCLATH
isr_tmr0
        btfsc   INTCON,T0IE       ; If TMR0 enabled
        btfss   INTCON,T0IF       ;    and TMR0 interrupt triggered
        goto    isr_tmr0_
        bcf     INTCON,T0IF       ; clear interrupt source
        movlw   ( .100 uS +$+1)/4 ; timer reload value
        movwf   1                 ; load timer
        ...
isr_tmr0_

von Chris (Gast)


Lesenswert?

movlw   ( .100 uS +$+1)/4 ; timer reload value
muss
 movlw   -( .100 uS +$+1)/4 ; timer reload value
sein, ist mir beim Editieren der Zeile ein Fehler untergekommen.

von Thomas M. (xt-fahrer)


Lesenswert?

Schön und gut, aber je mehr ich darüber nachdenke, umso unsinniger finde 
ich es, die einzige ISR für einen schöden Timer zu verschwenden.
Würde meine Lösung exakt zählen?

Gruß
T.

von Hans W. (stampede)


Lesenswert?

>Würde meine Lösung exakt zählen?
Nein, wenn du den Code von dir oben meinst. Du testest Timer0 auf 0. 
Wenn es unguenstig laeuft, kann es sein dass der Timer schon bei 1 oder 
2 oder sonst wo ist, und du den ueberlauf nicht richtig erkennst. Wenn 
musst du das Interruptflag pollen und dann den Sprung machen. Die 
exakteste Methode ist aber die ISR.

von Thomas M. (xt-fahrer)


Lesenswert?

Hans W. schrieb:
>>Würde meine Lösung exakt zählen?
> Nein, wenn du den Code von dir oben meinst. Du testest Timer0 auf 0.
> Wenn es unguenstig laeuft, kann es sein dass der Timer schon bei 1 oder
> 2 oder sonst wo ist, und du den ueberlauf nicht richtig erkennst. Wenn
> musst du das Interruptflag pollen und dann den Sprung machen. Die
> exakteste Methode ist aber die ISR.

Vor der mnloop-Marke wird TMR0 natürlich erstmalig korrekt geladen, das 
hatte ich vergessen dazuzuschreiben.
Wenn GIE und T0IF disabled sind, fungiert TMR0 doch als Zähler genauso 
präzise wie als Timer, oder nicht?

Gruß
T.

von Hans W. (stampede)


Lesenswert?

>Vor der mnloop-Marke wird TMR0 natürlich erstmalig korrekt geladen, das
>hatte ich vergessen dazuzuschreiben.
Ok, dann geht das wohl.
>Wenn GIE und T0IF disabled sind, fungiert TMR0 doch als Zähler genauso
>präzise wie als Timer, oder nicht?
Es reicht, T0IE (nicht T0IF) zu deaktivieren. Die Genauigkeit haengt nur 
von deinem Taktgeber ab.

von Chris (Gast)


Lesenswert?

Wenn du es einfach haben willst, prescaler auf 2, GIE oder auch nur T0IE
auf 0 und T0IF ist dein 102.4uS Flag welches du natürlich klären musst.
Die Zeit 102.4uS ist dann genau und wenn du einen Zähler mitlaufen 
lässt,
welcher nach Überlauf (carry) auf die Zahl 6 gesetzt wird dann sind das 
dann
genau 25600uS.

von Thomas M. (xt-fahrer)


Lesenswert?

Erlärst du mir, wie du auf die 102,4 µs kommst?

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.