Ik probeer een 1sec teller te maken met
timer 0 interrupt maar mijn klok loopt 3,5% te traag
Mijn prescaler staat op 1/2 en ik heb de 2 klokcycles
correctie toegepast voor TMR0.
Ik werk met een kristal van 4Mhz.

Eerst werkte ik met Timer2 interrupt maar ik heb die nodig
voor de PWM's te gebruiken op de 16F873A.

Ziet iemand een fout?



OPTION_REG = 0b10000000;      // Pullups off Prescaler to T0 1/2
     CMCON=0x07; CVRCON=0;         // Comparators off &Comparator volt ref off
     T1CON=0; T2CON=0;             // Disable Timer1 and 2
     CCP1CON=0; CCP2CON=0;         // Disable Capture/compare/PWM  1 & 2
     ADCON1=0x06; ADCON0=0;        // Disable AD
     SSPCON=0b00000101;            // Disable SPI / MSSP /serial port
     RCSTA=0;                      // Disable usart
     TRISA=0b00000000;             // Set all pins as outputs except buttons
     TRISB=0;                      // Set all pins as outputs
     TRISC=0;
     INTCON=0b10100000;            // Global Interrupts on & Timer0 int on
     TMR0=7;                       // T0=256-250+1 PS=1/2 (1 is correctie zie pdf)

void interrupt()                       // Every 500us  = 2khz
{
  if(INTCON.T0IF )                     // TMR0 Interrupt?
   {
     TMR0=7;                           // T0=256-250+1 PS=1/2 (1Mhz/(2*250) )
     if(scaler<1999) scaler++;         // 1 Sec has passed ?
     else
       {
         scaler=0;
         if(secs<59)secs++;            // Update secs
         else
           {
             secs=0;
             if(mins<59) mins++;       // Update mins
             else
               {
                 mins=0;
                 if(hours<23) hours++; // update hours
                 else hours=0;
               }
           }
       }
........ etc


Je interrupt routine doet veel te veel. Daar moeten enkel noodzakelijke dingen gebeuren maar vergelijkingen van minuten seconden horen daar niet in thuis.

TMR0=7;                           // T0=256-250+1 PS=1/2 (1Mhz/(2*250)

Omdat TMR0 nu een lage waarde heb kan je beter de Ps op 1/1 laten staan. Als je de timer wil fijn tunen kan je niet naar 7,5 gaan.

Ik had exact dezelfde interrupt routine
met timer2 en die klok liep perfect.

Er moet dus iets anders aan de hand zijn.

Misschien moet ik es testen met timer1

Ik zie twee fouten:

1) De prescaler wordt gereset tijdens het opnieuw laden van de timer, die moet je dus niet gebruiken.

2) Je laadt met een vast getal, maar de interrupt latency kan 1 of 2 cycles zijn, en dat laad je de timer met de verkeerde waarde. Je moet altijd een add instructie gebruiken.

Ik weet uit datasheet dat als je TMR0 met een
nieuwe waarde schrijft er 2klokpulsen geen TMR0
verhogingen zijn daarom moet je dus TMR0 reg met 2 verhogen
ter correctie.

Ik ging ervan uit dat als ik met PS van 1/2 ik dus TMR0
met 1 moest verhogen.

De timer loopt die niet door nadat de interrupt is genereerd. Naar de ISR gaan kost ook tijd.
TMR0 is daarin ook wezenlijk anders dan tmr2 die automatisch weer naar 0 springt. Je moet dan ook de tijd nodig naar de ISR mee rekenen.