|
|
View previous topic :: View next topic |
Author |
Message |
JPH
Joined: 02 Feb 2005 Posts: 9 Location: Finland
|
Critical timer |
Posted: Fri Mar 10, 2006 5:56 am |
|
|
Hello
Now I have a problem with timer1, how can I speed up this timer1 interrupt service routine. This is the only thing that processor do, so there should be plenty of time to execute it. I want to get 10us pulse in every 10ms. How can I speed up this ISR? Now it takes about 13us to execute whole timer1 isr. Can someone give me an example.
Code: |
#include <18F6722.h>
#DEVICE ICD=TRUE
#fuses H4,NOWDT,NOLVP,MCLR
#use delay(clock=32000000)
main()
{
setup_adc(adc_off);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256); //timer for generating signal
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); //timer for generating pulse
enable_interrupts(int_timer0);
enable_interrupts(global);
while(1)
{
}
}
#INT_TIMER0
int_timer0_isr()
{
set_timer0(65224); //16bit (1/(32000000/(4*256))*311=10ms
enable_interrupts(int_timer1);
}
#INT_TIMER1
int_timer1_isr()
{
set_timer1(65520);
if(edge==0)
{
output_high(pin_a5);
edge=1;
}
else if(edge==1)
{
output_low(pin_a5);
disable_interrupts(int_timer1);
edge=0;
}
}
|
|
|
|
sjbaxter
Joined: 26 Jan 2006 Posts: 141 Location: Cheshire, UK
|
|
Posted: Fri Mar 10, 2006 6:58 am |
|
|
Can you not just set timer0 to fire every 10ms and make the isr create the whole of the 10us pulse, ie.
Code: | #include <18F6722.h>
#DEVICE ICD=TRUE
#fuses H4,NOWDT,NOLVP,MCLR
#use delay(clock=32000000)
// 16bit (1/(32000000/(4*256))*311 = 10ms
#define PRE_LOAD_10ms 65224
main()
{
output_low(pin_a5);
setup_adc(adc_off);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256); //timer for generating 10ms interval
set_timer0(PRE_LOAD_10ms);
enable_interrupts(int_timer0);
enable_interrupts(global);
while(1)
{
}
}
#INT_TIMER0
int_timer0_isr()
{
set_timer0(PRE_LOAD_10ms);
output_high(pin_a5);
delay_us(10);
output_low(pin_a5);
}
|
_________________ Regards,
Simon.
Last edited by sjbaxter on Fri Mar 10, 2006 10:26 am; edited 2 times in total |
|
|
dorinm
Joined: 07 Jan 2006 Posts: 38
|
|
Posted: Fri Mar 10, 2006 7:20 am |
|
|
1: #use fast_io(A) , it eliminates a 2 BCFs (2x1 cycle) on TRISA
2: use
else
{ ...
}
instead of
else if(edge==1)
{ ...
}
...it eliminates a BTFSS (1,2 or 3 cycles) and a BRA (2 cycles)
try it and let us know ;) |
|
|
Ttelmah Guest
|
|
Posted: Sat Mar 11, 2006 10:17 am |
|
|
The key to understand, is that interrupts involve work. This is why on systems like the PC, it is common to find serial communication at high rates, loosing characters, except on modern units, where large hardware buffers are present. This despite having a processor, that can potentially execute hundreds of instructions in the interval between interrupts. Unfortunately, when an interrupt occurs, there is a lot of 'housekeeping', which has to happen, both before entering the interrupt routine, and then after leaving this.
As it stands, setting the timer 'on' to generate a time, works, but will cause problems if other tasks start to occur, where the time may become innaccurate, if there are a lot of other things to do. Personally, I'd always use a timer that can do the timing in 'hardware' if possible. If (for instance), you program timer2, to use 249 counts, with the /16 prescaler, and interrupt on every ten counts, you will get an interrupt every five mSec. Simply toggle a bit, and if it is set, execute the code to generate the pulse.
Now on the pulse, the 'best' solution, is to use the hardware to do this for you. The CTC channels, have the ability to clear a pin, after a programmed time, and will do this without needing a call to an interrupt handler. So:
Code: |
#int_timer2
void fivems_tick(void) {
static int1 toggle=false;
if (toggle) toggle=false;
else {
toggle=true;
CCPx=20;
set_timer1(0);
output_high(CCP_PIN);
}
}
|
If Timer1, is set to increment on 0.5uSec counts, then this will raise the pin (you will have to select which CCP you want, and which pin it uses), and drop it automatically 10uSec latter.
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|