Continue to Site

# PIC16F877A (timer1) accurate timing question

Status
Not open for further replies.

#### micro571

##### New Member
I've got the timer1 interrupt working. It's a 16 bit timer. I'm using a 20MHz oscillator.

I'd like to have a variable micros that keeps track of how long the program has been running. I'd like 10uS resolution.

Using this calculator: **broken link removed**
I found that I can get a 10uS timer period by setting the pre-scalar to 1:1 and timer offset to 0xffcd.

Code:
unsigned long micros = 0;

void interrupt isr(void){
if((TMR1IE)&&(TMR1IF)){
TMR1H = 0xff;  //TIMER OFFSET FOR 10uS Period
TMR1L = 0xcd; //TIMER OFFSET FOR 10uS Period
micros+=10;
TMR1IF=0;	// clear event flag
}
}

Questions:
- Am I doing this correctly, by setting the TMR1H and TMR1L values in the ISR or there a better way to do this?
- Do I need to account for the (time) length of the ISR to get an accurate count for my micros variable? If so, what should I set my timer period to (ie, 9.8uS or something)?

#### Pommie

##### Well-Known Member
You can get much greater accuracy by using the PWM module in Special Event Trigger mode. In this mode CCPR1H/L act as an interval timer for timer1 and so you get a resolution of 200nS without having to update any registers. I have example code somewhere if it helps.

Edit, just noticed you stated 10uS - not 10mS as I thought. This is tricky as 10uS is only 50 instructions and so any interrupt will tie up most of the processors time.

Mike.

Last edited:

#### dougy83

##### Well-Known Member
If you want to get an accurate period with TIMER1, you can subtract a constant (instead of just reloading) from the TMR1 count - this takes into account varying interrupt latencies.

Better still, you can use TIMER2 which allows you to set the period once and you're guaranteed accurate time (so long as the ISR triggers properly). The ISR is simplified. Also, you don't need to check TMR2IE if it's always going to be enabled.
Code:
void interrupt(){
if(TMR2IF){
micros+=10;
TMR2IF = 0;
}
}

#### Pommie

##### Well-Known Member
Dougy,

Did you know you can also set the period for timer1 with full 16 bit accuracy? If you want an interrupt every 47371 cycles then timer1 can do it - completely automatically. Check out the Special Event Trigger of the CCP module.

Mike.

#### micro571

##### New Member
To get the performance I need, I might have to use a delay in a loop then.

Is there a way for me to see how long a certain code segment takes to run?

I could toggle a pin, run then code, and toggle the pin again and look at the response on an oscilloscope, but is there an easier way?

Edit: Fixed typo.

Last edited:

#### dougy83

##### Well-Known Member
Did you know you can also set the period for timer1 with full 16 bit accuracy? If you want an interrupt every 47371 cycles then timer1 can do it - completely automatically. Check out the Special Event Trigger of the CCP module.

No, I was completely ignorant; never used CCP (or read about it). Looks very handy.

#### geko

##### Active Member
Dougy,

Did you know you can also set the period for timer1 with full 16 bit accuracy? If you want an interrupt every 47371 cycles then timer1 can do it - completely automatically. Check out the Special Event Trigger of the CCP module.

Mike.

You know I'd never noticed that feature, learn something new every day.

Better still, it's just what I need for something I'm working on at the moment that uses the ADC

#### Pommie

##### Well-Known Member
Geko,

On some chips the Special Events Trigger can also start the ADC for you when the period times out. On the 16 series it is only available on CCP2.

Mike.

#### blueroomelectronics

##### Well-Known Member
That mode is handy. I use it in my clock kit.

#### Pommie

##### Well-Known Member
Handy? Just bloody handy? It's bloody fantastic.

Said in best Monty Python voice.

Mike.

Status
Not open for further replies.

Replies
6
Views
7K
Replies
44
Views
3K
Replies
12
Views
2K
Replies
9
Views
1K
Replies
8
Views
1K