• AVR Freaks

AnsweredHot!timer0 interrupt - unable to correctly calculate overflow frequency

Author
marvinatorrr
New Member
  • Total Posts : 19
  • Reward points : 0
  • Joined: 2020/01/14 03:42:57
  • Location: 0
  • Status: offline
2020/01/18 07:03:26 (permalink)
0

timer0 interrupt - unable to correctly calculate overflow frequency

Based on my settings (500kHz, 1:2 prescale, preload of 252(2 ticks for writing to TMR2, 1 actual timing tick)) I expect to get a timer period of 16us. I use the equation
   
 //T0 freq = (Fosc/4)*Prescaler ratio
 // = (500k/4)*(1/2) = 62.5kHz = 16us
 //1 cycle = 16us

[/code]
 
But somehow after looking at the oscilloscope and working backwards i get a timer period of about 711us.
 
Using XC8 v1.34, PIC18F1220, MPLAB v5.30
 

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "header.h"



int count=0;

void init_ADC(void);
void init_interrupttimer(void);

void interrupt ISR()
{
    if(INTCONbits.TMR0IF)//check for flag timer0
    {
        TMR0=252;//preload
        INTCONbits.TMR0IF=0;//clear flag
        count++;
    }
    //T0 freq = (Fosc/4)*Prescaler ratio
    // = (500k/4)*(1/2) = 62.5kHz = 16us
    //1 cycle = 16us
    
    
    if(count>=1125) //18ms
    {
        PORTBbits.RB0=1;
    }
    if(count>=1250) //2ms
    {
            PORTBbits.RB0=0;
            count=0;
    }
}

uint16_t ADC_Result[2];
uint16_t error;
uint16_t ADC_Read(uint8_t channel)
{
    ADCON0 = (channel << 2);
    ADCON0 |= 0x03;
    
    while (ADCON0bits.GO_nDONE);
    return((ADRESH<<8 | ADRESL));
}

void main(void) {
    OSCCON = 0b00110110; //run mode, 500kHz, internal osc block
    
    init_ADC();
    init_interrupttimer();
            
    TRISBbits.RB3=0; //set as output
    TRISBbits.RB2=0; //set as output
    TRISBbits.RB0=0; //set as output
    
    CCP1CON = 0b10001100; //half bridge output
                          //p1a complements p1b pwm output with dead band control
                          //all active high
    
    
    
    T2CON = 0b00000000; //prescale 1:1, postscale 1:1
    PR2=124; //calculation PWM Period = [(PR2) + 1] ? 4 ? TOSC ?(TMR2 Prescale Value)
    CCPR1L = 62;
    //PWM1CON = 10; //dead band delay 0-127
    
    T2CONbits.TMR2ON = 1; //start timer
    
        while(1)
    {
        ADC_Result[0] = ADC_Read(0);
        ADC_Result[1] = ADC_Read(1); //0-1023
        
        PIR1bits.TMR2IF=0;
        while(PIR1bits.TMR2IF==0);
    }
    return;
}

void init_ADC(void)
{
    ADCON0 = 0x00; // ADC off, Vref+=AVDD, Vref-=AVSS
    ADCON1 = 0x7C; // AN0 and AN1 analog, all others digital
    ADCON2 = 0x92; // Right justified, ACQT=4 Tad, ADCS=Fosc/32
}

void init_interrupttimer(void)
{
    TMR0=0;//clear preload
    
    INTCONbits.TMR0IE=1;//enable timer0 overflow interrupt
    INTCONbits.GIE=1;//enable all global interrupts
    INTCONbits.PEIE=1;//enable peripheral interrupts
    INTCONbits.TMR0IF=0;//clear timer0 overflow flag
    
    T0CONbits.T0SE=0;//edge select low to high
    T0CONbits.PSA=0;//prescaler assigned
    T0CONbits.T0PS=0b000;//prescale 1:2
    T0CONbits.T08BIT=1;//8 bit timer
    T0CONbits.T0CS=0;//internal instruction cycle clock
}

Attached Image(s)

#1
1and0
Access is Denied
  • Total Posts : 10346
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: timer0 interrupt - unable to correctly calculate overflow frequency 2020/01/18 07:29:41 (permalink)
0
marvinatorrr
Based on my settings (500kHz, 1:2 prescale, preload of 252(2 ticks for writing to TMR2, 1 actual timing tick)) I expect to get a timer period of 16us. I use the equation
void interrupt ISR()
{
    if(INTCONbits.TMR0IF)//check for flag timer0
    {
        TMR0=252;//preload
        INTCONbits.TMR0IF=0;//clear flag
        count++;
    }
    //T0 freq = (Fosc/4)*Prescaler ratio
    // = (500k/4)*(1/2) = 62.5kHz = 16us
    //1 cycle = 16us
    
    
    if(count>=1125) //18ms
    {
        PORTBbits.RB0=1;
    }
    if(count>=1250) //2ms
    {
            PORTBbits.RB0=0;
            count=0;
    }
}


Your Timer0 overflows in (256 - 252) * 2 = 8 instruction cycles, before it gets a chance to exit the ISR.
 
#2
pippo18
Junior Member
  • Total Posts : 17
  • Reward points : 0
  • Joined: 2018/08/16 13:02:07
  • Location: FCUK
  • Status: offline
Re: timer0 interrupt - unable to correctly calculate overflow frequency 2020/01/18 07:50:25 (permalink)
0
yeah, and write to LAT registers, not PORT (C)
#3
pcbbc
Super Member
  • Total Posts : 1507
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: timer0 interrupt - unable to correctly calculate overflow frequency 2020/01/18 07:51:36 (permalink)
0
Yes PIC timers count up and timeout on wraparound to zero, not down.
Also, for regular Period interrupts, use a timer with a period register e.g. Timer 2 and PR2.
You won’t have to reload the timer each time, and you’ll not get any drift due to the ISR entry delay (or have to correct for it).
 
Edit: Sorry, my bad. See you are already using T2 for PWM.
post edited by pcbbc - 2020/01/18 07:56:44
#4
marvinatorrr
New Member
  • Total Posts : 19
  • Reward points : 0
  • Joined: 2020/01/14 03:42:57
  • Location: 0
  • Status: offline
Re: timer0 interrupt - unable to correctly calculate overflow frequency 2020/01/18 08:23:03 (permalink)
0
@1and0 sorry I'm not quite sure what you mean by (256-252)*2. What is the multiply by 2 about?

Edit: I see it now. Two instruction cycles per count.
post edited by marvinatorrr - 2020/01/18 08:26:33
#5
marvinatorrr
New Member
  • Total Posts : 19
  • Reward points : 0
  • Joined: 2020/01/14 03:42:57
  • Location: 0
  • Status: offline
Re: timer0 interrupt - unable to correctly calculate overflow frequency 2020/01/18 10:34:01 (permalink)
0
I still cant get it within the required time. I have tried increasing the prescale to 1:4 or lowering the preload value. How do I know how long I need to complete the ISR?
#6
1and0
Access is Denied
  • Total Posts : 10346
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: timer0 interrupt - unable to correctly calculate overflow frequency 2020/01/18 14:26:10 (permalink) ☼ Best Answerby marvinatorrr 2020/01/29 08:26:51
+1 (1)
marvinatorrr
I still cant get it within the required time. I have tried increasing the prescale to 1:4 or lowering the preload value.

In your Post #1 code, change this
    T0CONbits.PSA=0;//prescaler assigned

to this
    T0CONbits.PSA=1;//prescaler not assigned

and replace your ISR() with this
void interrupt ISR()
{
    if(INTCONbits.TMR0IF)//check for flag timer0
    {
        TMR0L -= (250 - 2 - 1);  // preload 2 ms
        INTCONbits.TMR0IF=0; //clear flag
        count++;
    }
   
    if(count == 18/2)  // ~18 ms
    {
        LATBbits.LATB0 = 1;
    }
    if(count == 20/2)  // ~20 ms
    {
        LATBbits.LATB0 = 0;
        count = 0;
    }
}

#7
marvinatorrr
New Member
  • Total Posts : 19
  • Reward points : 0
  • Joined: 2020/01/14 03:42:57
  • Location: 0
  • Status: offline
Re: timer0 interrupt - unable to correctly calculate overflow frequency 2020/01/18 22:06:35 (permalink)
0
This works but im not sure about:
 
Why did you use TMR0L instead of just TMR0 since we are using 8 bit timer in this case.
 
#8
1and0
Access is Denied
  • Total Posts : 10346
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: timer0 interrupt - unable to correctly calculate overflow frequency 2020/01/18 23:07:12 (permalink)
0
marvinatorrr
This works but im not sure about:
 
Why did you use TMR0L instead of just TMR0 since we are using 8 bit timer in this case.

Because TMR0L is the lower 8 bits of 16-bit TMR0, and Timer0 is setup as an 8-bit timer.
#9
pcbbc
Super Member
  • Total Posts : 1507
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: timer0 interrupt - unable to correctly calculate overflow frequency 2020/01/18 23:47:04 (permalink)
0
marvinatorrrWhy did you use TMR0L instead of just TMR0 since we are using 8 bit timer in this case.

Did you perhaps think L meant LONG?
 
In this case...
L = LOW byte
H = HIGH byte
and no suffix = the whole 16 bit register.
 
And (for peripherals that require 24 bit values) you may occasionally also encounter...
M = MID byte
#10
marvinatorrr
New Member
  • Total Posts : 19
  • Reward points : 0
  • Joined: 2020/01/14 03:42:57
  • Location: 0
  • Status: offline
Re: timer0 interrupt - unable to correctly calculate overflow frequency 2020/01/19 01:12:23 (permalink)
0
ah ok I see. And about the -1 and -2, is to account for the clear flag and count++ respectively?
#11
1and0
Access is Denied
  • Total Posts : 10346
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: timer0 interrupt - unable to correctly calculate overflow frequency 2020/01/19 09:44:36 (permalink)
0
pcbbc
And (for peripherals that require 24 bit values) you may occasionally also encounter...
M = MID byte

Microchip naming convention is Upper byte (bits 23-16), High byte (bits 15-8), and Low byte (bits 7-0).
#12
1and0
Access is Denied
  • Total Posts : 10346
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: timer0 interrupt - unable to correctly calculate overflow frequency 2020/01/19 09:52:04 (permalink) ☄ Helpfulby marvinatorrr 2020/01/29 08:26:34
0
marvinatorrr
ah ok I see. And about the -1 and -2, is to account for the clear flag and count++ respectively?

No. The -2 accounts for the two-instruction-cycle increment inhibited when the TMR0 register is written, and the -1 accounts for the instruction cycle of writing to the TMR0 register. Bonus: The -= accounts for the time elapsed between TMR0 interrupt and writing of the TMR0 register.
#13
Jump to:
© 2020 APG vNext Commercial Version 4.5