View previous topic :: View next topic |
Author |
Message |
notbad
Joined: 10 Jan 2013 Posts: 68
|
Accuracy problem in timer0 interrupt |
Posted: Thu Jan 10, 2013 6:59 am |
|
|
Hi
First I wrote this small code which works fine and timer0 overflows every 64us.
crystal = 16Mhz so machine cycle=0.25 us
0.25 * 256 = 64 us
Code: |
#include <16F873A.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(clock=16000000)
#int_TIMER0
void TIMER0_isr(void){
output_toggle(pin_a0);
}
void main()
{
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
set_tris_a(0);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
while(true);
} |
But when I add a line to make timer0 start from 128, things go wrong.
Overflow interval should be: 0.25 * 128 = 32 us but it overflows every 41.75 us!
Code: | #int_TIMER0
void TIMER0_isr(void){
set_timer0(128);
output_toggle(pin_a0);
} |
BTW CCS version is 4.084. Any ideas? |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9176 Location: Greensville,Ontario
|
|
Posted: Thu Jan 10, 2013 7:45 am |
|
|
hmm..
set_timer0(128);
You've added code inside the ISR..
The PIC has to execute that code...
That takes time !!
Try another value( say 64,27,192) and see what happens.. |
|
![](templates/subSilver/images/spacer.gif) |
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Jan 10, 2013 8:33 am |
|
|
It takes time for the processor to enter you ISR routine, several registers are stored on entry and restored on exit. Depending on your processor the number of stored and restored registers differs, for a PIC16 it takes about 20 instruction times before it starts executing your code. A PIC18 approximately doubles that.
I don't have a compiler here so I can't check the actual instruction counts. But by the time you set the timer to 128, the counter would already have increased to about 25. You loose these 25 counts == 6.25us
try changing the code to: Code: | set_timer0( get_timer0() + 128); |
Note that you are close to hardware limitations. You are running Timer1 at it's maximum rate, i.e. 1 tick is equal to 1 instruction time. Entering the ISR and restoring the registers takes about 20 + 20 = 40 instruction times. Then a few instructions inside the ISR, say 10. With Timer0 triggering each 128 ticks you are already spending 50% CPU time. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19375
|
|
Posted: Thu Jan 10, 2013 9:11 am |
|
|
and (of course), if all you actually need to do, is generate a square wave, then the PWM can do this without using _any_ processor time....
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Fri Jan 11, 2013 9:26 am |
|
|
I assume you understand that with the interrupt density you have programmed, you have an awful lot of processor time devoted to nothing BUT serving the interrupt.
Are you planning to do anything else other than toggle that PIN ??
If so, use another method to generate your 64 us square wave
several simple hardware methods come to mind
such as the 74HC40xx long chain dividers , slaved to your clk out pin on the pic.
PIN #15 of the 74HC4060 with 16mhz IN , gives a nice divide by 2^10 - and 2^9 as well as 2^11th are standing by as well
if ALL you need is the square wave - lose the pic too!l LOL ![Very Happy](images/smiles/icon_biggrin.gif) |
|
![](templates/subSilver/images/spacer.gif) |
notbad
Joined: 10 Jan 2013 Posts: 68
|
|
Posted: Sat Jan 12, 2013 6:05 am |
|
|
Thank you guys
I got your point.
Actually the code above is not the final project. I’m still getting to know timers. My project is to generate a SPWM signal with variable frequency. I need to make accurate time intervals so I think I should use a 16bit timer. Right?
It seems like setting the timer value after going to ISR is useless.
My question is how can I get timers to auto-reload (as in AVRs) with the defined value exactly after overflow?
Sorry for bad english ![Embarassed](images/smiles/icon_redface.gif) |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19375
|
|
Posted: Sat Jan 12, 2013 8:09 am |
|
|
You don't.
The timer on the PIC, operate the other way round, always counting 'up', and resetting when they wrap. However:
Answer one, add a value to the count. This is what Ckielstra posted.
Answer two, switch to a DSPIC.
Answer three, use timer2, This allows you to set the point when it resets.
Answer four, from what you are describing far better/easier, and more accurate to use a programmable frequency synthesiser IC.....
16bit, implies longer intervals. With longer intervals you have more counts, so potentially more resolution, but lower frequency.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sat Jan 12, 2013 1:00 pm |
|
|
Quote: |
more accurate to use a programmable frequency synthesiser IC.....
|
you might try the NCO feature of the 16f1509 and its junior partners |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19375
|
|
Posted: Sun Jan 13, 2013 2:56 am |
|
|
Or possibly the HRPWM, depending on the actual frequencies required. The same chip has this (you use the CLC module - see AN1476).
Just to confuse you, the Microchip 'search data sheets' selection, doesn't know about this chip, but put it into the main site search, and then the first entry goes to the data sheet page. They are available.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
|