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.
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
Könnte es sein, daß ich die Viertel vom Oszillatortakt und die Viertel vom Prescaler einfach zusammengeschmissen habe? Gruß T.
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.
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.
Und bei einem Timer Preload von 131 hat er dann 100µs. Also stimmt seine Rechnung.
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.
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ß
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.
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_
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.
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.
>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.
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.
>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.
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.
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.