View previous topic :: View next topic |
Author |
Message |
Bryan
Joined: 23 Apr 2005 Posts: 73
|
Timer inconsistencies |
Posted: Mon Oct 09, 2006 6:21 pm |
|
|
I have been working with timers awhile and in my current application I have noticed some inconsistencies when working with them.
I am working with a 20 MHz clock, so when doing timer calculations I use Fosc/4 or 5 MHz which produces a 0.2 us tick of the timer with no prescaler. I toggle an output and view this on an oscilloscope for timer0 and I see what is expected - A 13.107 ms pulse width (65536 * 0.2). Now, when I use set_timer0(), and I want the timer to interrupt very quickly (say on an 8 us interval) I use this logic: it needs to tick 40 times at 0.2 us per tick to interrupt every 8 us so I use set_timer(65536-40) to accomplish this. While theoretically this should work, when measured on my scope the output is approximately 18 us! I tried setting a lower value in the set_timer0() and apparently this 18us is the best that can be done because it never gets faster.
Anyone know why this is or any way to get a faster interrupt if there are limits on the pic? |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
Re: Timer inconsistencies |
Posted: Mon Oct 09, 2006 6:34 pm |
|
|
Bryan wrote: | Anyone know why this is or any way to get a faster interrupt if there are limits on the pic? |
The problem you are seeing is due to the context saving in the interrupt handler.
To solve the problem (varies by compiler release) use the fast keyword.
You are responsible for storing any registers that might change. It get trickier in a system which has an 18F series PIC with the broken shadow register implementaion (most 18F series PICs in other words). To work around this problem you have to save and restore the BSR, Status and WReg yourself plus execute a normal "retfie 0" at the end of the handler. This will incease. Any registers used by the handler should be in the access bank (hint use #locate) unless access via movff instructions.
This will significantly reduce the interrupt handler latency. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Bryan
Joined: 23 Apr 2005 Posts: 73
|
|
Posted: Mon Oct 09, 2006 7:09 pm |
|
|
I guess I'm not familiar with how you would do this in C. It sounds like you are referring to these operations in ASM. For timer0 could you post a simple sample code snippet showing how to restore the BSR, status, and WReg plus execute the "retfie 0"? Also, any more hints on how to use #locate to accomplis hthis last bit would be appreciated! |
|
|
Bryan
Joined: 23 Apr 2005 Posts: 73
|
|
Posted: Mon Oct 09, 2006 7:14 pm |
|
|
Another question: If I used the CCP1 interrupt could I declare this with the keyword fast as well to speed up latency? I was having trouble with my 20 MHz clock and the CCP wasn't capturing all of the edges in an 8us period pulse and I assumed it was because of my clockspeed. Now I am thinking I may be able to make it work if I use Fast interrupts. Anyone know if this might speed it up enough? |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Tue Oct 10, 2006 12:41 am |
|
|
Code: |
volatile int HI_STATUS;
volatile int HI_BSR;
volatile int HI_WREG;
#int_timer3 fast
void my_tmr3(void)
{
_asm
movff STATUS, HI_STATUS
movff BSR, HI_BSR
movff WREG, HI_WREG
_endasm
// c code goes here
_asm
movff HI_STATUS, STATUS
movff HI_BSR, BSR
movff HI_WREG, WREG
retfie 0
_endasm
}
|
Depending on your compiler version, you may be limited to a single high priority handler. If you need to have multiple high priority handlers then you can fool the compiler by using it to install the first handler (same as previous example) then setting up the other interrupts yourself. For example for timer 2 you would set the priority bits to high, enable the interrupt - do not use the enable_interrupts statement for this instead access the appropriate INTCONx bits directly.
You will have to clear the interrupt yourself because the compiler does not know it is there. Also you need to add the NOCLEAR directive to the original #int_Timer3 directive otherwise if you process a timer2 interrupt it will clear the timer3 flag as well so you could miss interrupts. Therefore your handler must clear its own interrupt sources. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
|