[pic] TMR0 initialisieren

OP #2261790
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.
#2262003
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.
OP #2262066
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.
Gast #2262115
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_
#2262510
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.
OP #2262542
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.
#2262546
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.
Gast #2262774
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren