Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] PIC16F 8-bit uC: Timer Interrupts, Accurate Timekeeping

Status
Not open for further replies.

zia.newversion

Member level 5
Joined
Mar 28, 2010
Messages
83
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Location
Pakistan
Activity points
2,188
I was reading a book on PIC microcontrollers. I was particularly interested in some material on timers. I read about clock cycles, instruction cycles, prescalars, timer registers, timer interrupt etc...

The topic of timer-interrupts is what I really wanted to know more about. I know a little bit about hardware interrupts, but this is the first time I am reading about timer interrupts.

I gained a lot from the book. But I have a little confusion. Here is an example scenario:

I have a 4MHz system clock (external LP quartz oscillator). I need to increment a certain register every 1ms. 8MHz means 0.125µs per clock cycle and 0.5µs per instruction cycle. By setting 1:8 prescalar, the timer increments every 4µs. After the first 256 increments, timer interrupt is generated. So in this case, after every 1.024ms, interrupt is generated. That's somewhat accurate. But say I cannot afford this error. That would mean I need exactly 250 increments to capture the interrupt with accuracy. So if I start with value 6 stored in TMR0, I would capture the interrupt just in time.

That is good for the first 1ms. Now, the ISR for that timer interrupt might have upto 100 instructions. That would take 50µs. How would I do the next 1ms? I could take those 50µs into account, save 19 in TMR0 (0.5µs) do 3 NOPs (1.5µs) and then wait for next interrupt which will be
----- (256-19)x4µs = 948µs -----
later... So that makes my 948+1.5+0.5+50=1000µs.
Well, that certainly is a lot of calculation. And a lot of calculation if the number of instructions in ISR is other than 100.
And what if the number of instructions is conditional? Shall I do those calculations for every possible path?
For all that depends, ISR could have a single to thousands of instructions!​

So, I don't think it should get that complicated. I might be missing something. There must be a workaround. And above all, that "feels" like a non-professional programming approach.

If someone has worked with timers before, could he please help me find a solution?
 

Hi,

When the timer is enabled, it start counting what ever uC do with other instruction.

That means, you load timer-registers with value for 1ms and enable it; then uC can do anything else, but after timer-register overflow (ie after 1ms) it raise interrupt-flag and go to ISR.

Commencing of ISR, you clear timer-interrupt-flag and reset register-value for next count of 1ms. (Note that since it is inside of ISR, Global-interrupt setting is disabled) Now you can do other works. Only condition is you shouldn't spend more than 1ms inside the ISR. At exit of ISR global-interrupt will be enabled and timer-interrupt will direct uC again to ISR after elapsing 1ms.
Than you,
 

The timer will still be incrementing during the interrupt. Just pre-load the timer at the start of the interrupt. Providing you exit the interrupt within 1mS, all should be well as DineshSL has said.

You could use two timers, one dedicated to the 1mS interrupt.
 

I am getting what both of you mean.
You are saying that once the ISR is under commencement, the the timer keeps running in background while the instructions in ISR are executed step by step. That is self explanatory, and logically acceptable.
I also get that ISR should not take more than 1ms or the next interrupt will be missed.

But the confusion is still there. I loaded the TMR0 register with value 6... After exactly 1ms, interrupt was generated and processed. While the uC starts working on the ISR, the timer restarts. Will it restart from 6 or from 0???
If it restarts from 0, it won't take exactly 1ms to generate interrupt like previous cycle... Rather it will take 1.024ms, like I mentioned in my previous post... That means that first interval is 1ms, all the next intervals are 1.024ms onwards.
However, if it starts again from 6, Then we are good. Because during the execution of ISR, the timer takes exactly 1ms for the generation of next interrupt. Then the whole problem is solved.
 

It doesn't restart, it just keeps going and overflows back to 0.

Pre-load the timer in the interrupt

Code:
if(TMR0IF)
    {
    TMR0 = 6;

    /* do your thing here */

    TMR0IF = 0;  /* Clear flag */
    }
 
Last edited:
I got it.
Thanks a lot... Sorry I didn't try writing a code first. I try to understand and build an algo first.

Just one other thing. Can you explain the clearing of flag? What flag? And why does it need to be cleared? And why exactly at that place in the code...
 

When the timer overflows, it sets an interrupt flag to signal the processor that it has overflowed. If the timer interrupt is enabled, the processor jumps to the interrupt routine. (Simplified explanation).

You can test which interrupt has occurred by testing the flags, several interrupts share the same vector so you need to figure out which one has caused the interrupt. You do that by testing the flags.

if(TMR0IF) /* Timer 0 interrupt flag */

blah blah

else if(TMR1IF) /* Was it timer 1 ? */

blah blah

etc.

After servicing the interrupt, you clear the flag so that the interrupt is reset.
If you don't clear the flag, the program will immediately go back to the interrupt routine thinking that an interrupt has occurred.

It is useful to use Mplab Sim to step through your code. You can place a breakpoint in the interrupt routine and use the stopwatch to time your interrupts.
 
This is now officially solved. Thanks a lot.
By the way, I know C, but I haven't come to applying that knowledge to microcontrollers yet. Will do that soon enough. However, I did understand what you wanted to imply, perfectly.
And yeah, I've done that MPLAB debugging a couple times... Didn't think of it just now, though. Thanks again.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top