View previous topic :: View next topic |
Author |
Message |
Izzy
Joined: 27 May 2007 Posts: 106
|
200 ms Timer Interrupt? |
Posted: Mon Mar 31, 2008 7:43 pm |
|
|
Hello,
I have done enough search in this forum to find out a way to interrupt after every 200-250 ms but I havent been able to find an answer.
Please let me know a way to interrupt after every 200ms without interrupting multiple times and then calling the function
I am using 40Mhz cyrstal oscillator and a PIC18f4685
I think the max time I can get from Timer 1 is 52.xx ms
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8)
40000000/4 = 10000000
1/10000000 = 0.1us
0.1 * 8 = 0.8us
0.8us * 65536 = 52.43ms
Thanks |
|
|
w2drz
Joined: 27 Dec 2006 Posts: 55 Location: Western New York - USA
|
|
Posted: Mon Mar 31, 2008 9:53 pm |
|
|
Hi,
Look at timer 0,
#define RTCC_INTERNAL 0
#define RTCC_EXT_L_TO_H 32
#define RTCC_EXT_H_TO_L 48
#define RTCC_DIV_1 8
#define RTCC_DIV_2 0
#define RTCC_DIV_4 1
#define RTCC_DIV_8 2
#define RTCC_DIV_16 3
#define RTCC_DIV_32 4
#define RTCC_DIV_64 5
#define RTCC_DIV_128 6
#define RTCC_DIV_256 7
#define RTCC_OFF 0x80
#define RTCC_8_BIT 0x40
tom |
|
|
Guest_7068 Guest
|
|
Posted: Mon Mar 31, 2008 9:57 pm |
|
|
Not happening.
You will need another counter inside your ISR to decide when to call the function:
Code: |
int8 count = 4;
#INT_TIMER1
void timer1_isr(void)
{
if (--count ==0)
{
call_my_function();
count = 4; // Re-initialize count.
}
}
|
|
|
|
w2drz
Joined: 27 Dec 2006 Posts: 55 Location: Western New York - USA
|
|
Posted: Mon Mar 31, 2008 10:52 pm |
|
|
I am using 40Mhz cyrstal oscillator and a PIC18f4685
I think the max time I can get from Timer 1 is 52.xx ms
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8)
40000000/4 = 10000000
1/10000000 = 0.1us
0.1 * 8 = 0.8us
0.8us * 65536 = 52.43msHi,
To clarify what I suggest if you have timer 0 to use,
setup_timer_0(T0_INTERNAL | T0_DIV_BY_32)
// this will be (1) int for 52.4288 times 4 = 209.7152 ms
#INT_RTCC
void T0_isr ()
{
//set flag to be used for 209.7152 ms use
// if need exact 200 ms then it is more code for that use
} |
|
|
Ttelmah Guest
|
|
Posted: Tue Apr 01, 2008 2:21 am |
|
|
It depends what pins and timers are not used in your project.
Simplest, is probably just to implement a faster tick, and count.
You can get a value _slower_ than this (or faster), using Timer0.
Timer0, has a maximum division, of:
/4(fosc/4) /256(prescale) /65536
So you can give an interrupt just slightly slower than this, using a prescaler of 32, to give:
/4 /32 /65536 = /8388608 = 4.768* per second = 209.7mSec.
However if you 'must' have really close to 200mSec, then program a PWM output pin, and feed this back into the TOCKI input.
You can setup (say) the PWM to use the /16 prescale, and /121, which will generate a pulse at 40000000/(4*16*122)Hz = 5123Hz. Then use Timer0, in 8bit mode, with a /4 prescale from this, to give 5123/(4*256)Hz = 5.00288Hz
199.884mSec
Best Wishes |
|
|
Matro Guest
|
|
Posted: Tue Apr 01, 2008 4:58 am |
|
|
What you ask is not possible to do without external hardware...
Matro. |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Tue Apr 01, 2008 6:40 am |
|
|
Hey guys,
Thanks a lot for help.
I thought Timer0 was a 8 bit timer. So its a 16 bit timer then?
No it does not need to be exact 200ms...something close should be good enough.
Code: | setup_timer_0(T0_INTERNAL | T0_DIV_BY_32)
// this will be (1) int for 52.4288 times 4 = 209.7152 ms |
Few things I really want to check with you guys and make sure I am not following the wrong direction..
Can you guys briefly describe the difference between RTCC, Timer0, Timer 1 and Timer 2. What are their max prescaler? Howmany bit are those timers? What is the difference between Internal timer and external timer? Can we use internal oscilator as a clock for timers using setup_osc...?
I know most of these stuff but I think I am missing something. I would really appreciate if some one can briefly go over this so that I can make sure what I know is right or wrong.
Thanks in advance. |
|
|
Ttelmah Guest
|
|
Posted: Tue Apr 01, 2008 8:55 am |
|
|
Timer0, is an 8bit timer on the older chips. On the newer chips, it is programmable to be an 8bit, or 16bit timer. The constant 'RTCC_8_BIT', puts it back to 8bit mode for compatibility, otherwise it runs as a 16bit timer. :-)
Best Wishes |
|
|
Ttelmah Guest
|
|
Posted: Tue Apr 01, 2008 9:09 am |
|
|
For your other question, there is a application note on the MicroChip site, which describes the timers. Reading the data sheet is the main source of data.
The timers differ in where they can take their inputs 'from' (some allow external pins), how many bits they have, what prescalers they have, what postscalers they have, what resets them, and what they feed. So timer0 (which is also the RTCC - no difference, it is just that on the old chips it was referred to by this name), supports operating off Fosc/4, or the T0CKI pin. A prescaler of 1:1, to 1:256, in binary values only, and counts to 256, or 65536. It's only output, is the TMR0IF. Conversely, Timer2, can only come from Fosc/4, has just four prescale values, is only 8bit, but can be reset automatically at any count. It's output can be routed to run the SSP. It also has a postscaler before feeding the interrupt, making it the 'best' timer in general, for generating exact divisions, to feed an internal 'tick' interrupt. Timer1, supports it's own external oscillator, and can run the PWM (on later chips, Timer3 can also be used for this).
Best Wishes |
|
|
inservi
Joined: 13 May 2007 Posts: 128
|
|
Posted: Wed Apr 02, 2008 3:50 am |
|
|
Hello Izzy.
For get interrupt for just 200mS, you can set your timer0 for interrupt every 209.7 as decribed Ttelmah. Then, simply set the timer0 counter to the right value (greater than 0) after each interrupt.
If 65536=209.7ms then :
9.7/200 = 0.485
65536*0.485 = 3178.4 = 9.7ms
65536-3178= 62358 = 200ms
Code: |
#INT_RTCC
void T0_isr ()
{
set_timer0(62358) // for 200 ms
...
your code
...
}
void main() {
...
setup_timer_0(T0_INTERNAL | T0_DIV_BY_32) = 209.7152 ms
set_timer0(62358) // for 200ms
enable_INTerrupts ( INT_TIMER0 );
enable_INTerrupts ( global );
...
|
That is very simple.
Best regards,
dro _________________ in médio virtus |
|
|
Ttelmah Guest
|
|
Posted: Wed Apr 02, 2008 4:53 am |
|
|
The problem is that it takes _time_ to get into the interrupt. Running off /256, it should be OK (provided there are no other interrupt driven devices), but normally this gives the problem of variable accuracy, as on occasions the clock will already have incremented when you reach the routine. So you end up not getting the required timing...
Best Wishes |
|
|
inservi
Joined: 13 May 2007 Posts: 128
|
|
Posted: Wed Apr 02, 2008 6:01 am |
|
|
Hello Ttelmah,
You are right. But after little adjusting, the timing will be stable and reliable. correct ? I already used this method with success. I'm maybe not need the same precision ?
Best regards,
dro. _________________ in médio virtus |
|
|
Ttelmah Guest
|
|
Posted: Wed Apr 02, 2008 10:29 am |
|
|
It can be made to work well, provided you don't have anything 'asynchronous' happening. If (for instance), you have interrupt driven serial comms, you will always run into the problem that if you are inside the serial interrupt, when the tick occurs, the amount of the time error will then be different from the normal occasions...
Best Wishes |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Apr 02, 2008 10:47 am |
|
|
Try the technique below to correct for the unknown delay: Code: | set_timer0( get_timer0() + 62358 ) // for 200 ms | This has the advantage that it can correct for a variable delay like when another interrupt is comming in between. A minor problem in this solution is that if the timer increments in between the reading and writing of the timer value than you get an offset by 1 error. |
|
|
inservi
Joined: 13 May 2007 Posts: 128
|
|
Posted: Wed Apr 02, 2008 11:12 am |
|
|
Thank you Ttelmah and ckielstra. _________________ in médio virtus |
|
|
|