|
|
View previous topic :: View next topic |
Author |
Message |
Sid2286
Joined: 12 Aug 2010 Posts: 119
|
Setting up timer1 |
Posted: Thu Nov 06, 2014 2:06 am |
|
|
Hi,
I am trying to set a timer to 1millisec delay , but not able to achieve it.
My code is as follows:
Code: |
#include <18F2520.h>
#device ICD=TRUE ADC=10
#fuses HS, INTRC_IO,NOLVP,WDT128
#use delay (clock=8000000)
static int count = 0;
#INT_TIMER1
void timer1_isr()
{
count++;
}
// Calculation 8Mhz divided internally by 4->2Mhz
// i.e 0.5 usec for one cycle
// Prescale = 1->1*0.5usec->0.5usec
// so for delay of 1msec 0.001/0.5u -> 2000 counts 65536-2000= 63536
void main()
{
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
set_timer1(63536);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
while(true)
{
if(count>=500)
{
output_toggle(Pin_C0);
count=0;
set_timer1(63536);
}
}
} |
and using 1msec I want to blink the LED after 500mSecs which is not happening.
kindly help!
sid |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Nov 06, 2014 2:40 am |
|
|
Tell us what is happening.
Then we can make an informed guess at what your problem could be.
Mike
You could try modifying your ISR like this
Code: | {
count++;
set_timer1(63536);
} |
|
|
|
Sid2286
Joined: 12 Aug 2010 Posts: 119
|
|
Posted: Thu Nov 06, 2014 2:51 am |
|
|
well, the timer is not running as expected, sometimes the LED toggles at 500msec and sometime it takes 10 secs.
I tried commenting INTRC_IO even that didnt help.
again I tried as what you suggested but even that is not helping. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Thu Nov 06, 2014 3:32 am |
|
|
Start with how often the timer will tick.
8000000/(4*65536)= 30.5 * per second. Not 1mSec....
set_timer, only applies _once_. The other loops to the interrupt, all just count to 65536....
Then look at 'count'. You test for count being >500. What is the largest number that an int8 can hold?....
Don't fiddle directly with the timer count. Problems with this are enormous. What happens if the timer wraps between writing one byte and the other?. Remember also the timer _will_ have counted quite a few cycles before it arrives in the interrupt.
Remember also, just how much time an interrupt takes. If your timer was being called every 2000 counts, it'd be using over 4% of the processor's time. Lower frequency is better, especially since the clock you are using is not that accurate.
The below shows a 'trick' way, by just updating the MSB, to give 100 interrupts per second.
So:
Code: |
#include <18F2520.h>
#device ICD=TRUE ADC=10
#fuses INTRC_IO,NOLVP,NOWDT //you were selecting two oscillators and
//the watchdog
#use delay (clock=8000000)
int count = 0; //a global doesn't need to be static. If it is, it is already
//initialised to 0.
#byte TIMER1_HIGH=getenv("SFR:TMR1H")
#BIT RD16 = getenv("BIT:RD16")
#INT_TIMER1
void timer1_isr()
{
TIMER1_HIGH+=177;
count++;
}
//Timer1, will now count 65536-(177*256) cycles = 20244
// Calculation 8Mhz divided internally by 4->2Mhz
// i.e 0.5 usec for one cycle
// Prescale = 1->1*0.5usec->0.5usec
// so counting to 20244 gives 98.8 interrupts per second
void main()
{
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
RD16=0;
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
while(true)
{
if(count>=98) //remember you are counting from 0
//This gives 99 counts, so 98.7:99 less than 0.2% error
{
count=0;
output_toggle(Pin_C0);
}
}
}
|
If you must tick at 1mSec, then use timer2, that can be directly programmed to do this:
setup_timer_2(T2_DIV_BY_1,199,10);
Gives an interrupt every (199+1)*10 counts = 2000. |
|
|
|
|
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
|