Timer0 PIC18F4550: tijd berekenen

Hallo,

Ik wou de tijdsduur tussen 2 interrupts van timer0 bij PIC18F4550 uitrekenen en dacht dat met volgende formule te doen:
1/(20 MHz / 4 / 256 / 2^16) = 3.355 sec
-de kristal die ik gebruik is 20 MHz
-ik ging er van uit dat de pic 4 clockpulsen nodig heeft om 1 instructie uit te voeren
-de prescaler staat op 1/256
-16 bit modus: de interrupt wordt uitgevoerd wanneer de 2 bytes 256 zijn = 2^16

Maar... als ik tel is op 120 seconden tijd de led 86 keer aan of uit: 120/86 = 1.395 sec.

Wat doe ik fout in mijn berekening?

Dit is de code die ik gebruik en de instellingen in winpic zitten in bijlage:

code:


;instellingen timer0
T08BIT = 0    ; 0= 16 bit, 1= 8 bit
T0CS = 0 ; 0 = timer, 1 = counter (stgt bij T0CKI pin)
T0SE = 0 ; indien counter: 0 = stgt bij low to high op T0CKI pin, 1 = bij high to low

;prescaler:
PSA = 0 ; prescaler gebruiken voor timer0 teller?: 0 = gebruiken, 1 = niet gebruiken
T0PS0 = 1
T0PS1 = 1
T0PS2 = 1
; 111 = 1/256
; 110 = 1/128
; 101 = 1/64
; 100 = 1/32
; 011 = 1/16
; 010 = 1/8
; 001 = 1/4
; 000 = 1/2

; formule tijd (s) = 1 / (20*10^6 Hz / 4 / prescale / (256 of 2^16 - startwaarde timer + 2) )

GIE = 1  ; schakel interupts in het algemeen in
TMR0IE = 1 ; schakel timer0 overflow interrupt in

TMR0ON = 1   ; start timer0

procedure interruptprocedures is
          pragma interrupt    ; deze procedure wordt uitgevoerd wanneer er EEN interrupt is
          if TMR0IF == 1 then    ; timer0 overflow interrupt flag: kijk of het gaat om een interrupt door timer0
                                     ; bij 8 bit: FFh --> 00h, bij 16 bit: FFFFh --> 0000h
             if groenled == 1 then
               groenled = 0
             else
                groenled = 1
             end if

             TMR0H = 0  ; stel waarde timer in (TMR0H wordt pas echt geschreven na TMR0L te schrijven)
             TMR0L = 0
             ; indien je deze waarden wil uitlezen: TMR0H krijgt pas de juiste waarde na TMR0L te lezen
        
             TMR0IF = 0 ; interrupt flag terug op 0 zetten
          end if
end procedure

forever loop
end loop

CPU clock staat niet op 20MHz, maar op 48MHz (96MHz / 2). Timerclock is dan 48/4=12MHz.   (1/(12000000/256/65536) = 1.3981 sec.)
Waarom gebruikt iedereen toch timer0 voor zulke zaken? (timer2 is een stuk handiger; die heeft een auto-reload functie en heb je geen omkijken naar...)

Arco - "Simplicity is a prerequisite for reliability" - hard en software ontwikkeling: www.arcovox.com

Blijft dat je moet weten wat de bon-klok van je timer is om de boel te kunnen relateren aan "real-time".

De timer op nul zetten in de interrupt routine is niet verstandig. Ik denk dat ie gewoon doorloopt. Dus als ie ondertussen doorgeteld is naar zeg "3" dan zet JIJ hem weer op nul. Het zou best kunnen dat dit nu niet gebeurt omdat de prescaler op 256 staat dus dat ie nog steeds op nul staat als jij hem schrijft. Maar details als: "reset de prescaler als je de timer schrijft?" weet ik niet uit m'n hoofd. In bepaalde scenarios zal dat handig zijn. Als de makers daaraan dachten toen ze het aan het maken waren, dan zit dat er in. En dan verlies je toch steeds een paar clock cycles....

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

Bedankt!
Dat had ik inderdaad over het hoofd gezien, nu klopt de uitkomst exact!

PS Dat van die timer op 0 te zetten was eigenlijk bedoeld de startwaarde van de timer te kunnen instellen (wat ik in dit voorbeeld niet gedaan heb):
formule tijd (s) = 1 / (20*10^6 Hz / 4 / prescale / (256 of 2^16 - startwaarde timer + 2) )