View previous topic :: View next topic |
Author |
Message |
Vlad
Joined: 03 May 2004 Posts: 8
|
Problem with Timer. Please help |
Posted: Mon May 03, 2004 3:38 pm |
|
|
Here I am trying to finish the timing equipment for a local car club by friday, and my timer is acting up. I know it is some silly thing, but I cannot see what I am doing wrong.
All I am trying to do is to count the milliseconds using Timer1. Frequency of my crystal is 40Mhz. I am putting out a square wave too, in order to see how whats going on.
Code: |
#int_timer1
void timer1_isr()
{
counter++ ;
if(flag)
{ output_low(PIN_B7);
flag=0;
}
else
{ output_high(PIN_B7);
flag=1;
}
set_timer1(1250);
}
//- from main ----------
counter=0; // ms counter
setup_timer_1(T1_INTERNAL);
set_timer1(1250);
enable_interrupts(INT_TIMER1);
while(input(SW1)==1){}
enable_interrupts(GLOBAL);
while(input(SW2)==1){}
//-- and then it displays the counter ---
|
I am getting around 6ms timeout right now, with those numbers. Weird thing is, if I try to change the count value with set_timer1 nothing changes :( .
Please help us have neat timers for racing
Thanks,
Vlad |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon May 03, 2004 3:54 pm |
|
|
Quote: | Frequency of my crystal is 40Mhz. |
Please verify whether you are attempting to use a 40 MHz crystal, or
are you really using a 10 MHz crystal with the 4x PLL oscillator mode ?
Also,
1. What PIC are you using ?
2. Please post your #fuses statement.
3. Also post your #use delay statement. |
|
|
Vlad
Joined: 03 May 2004 Posts: 8
|
|
Posted: Mon May 03, 2004 10:31 pm |
|
|
1. PIC16F877A
2. I did not specify any fuses
3. #use delay(clock=40000000)
I am pretty sure it is 40Mhz because that is what it says on the crystal oscillator. |
|
|
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Mon May 03, 2004 10:55 pm |
|
|
On PIC16 series you can not have a crystal faster than 20MHz. That's the maximum device speed.
Even on PIC18s you can not have a 40MHz crystal. If you want to operate at 40Mhz, you have to use a 10MHz crystal and activate the 4X PLL oscillator.
And it is always a good idea to specify the fuses. The NOLVP fuse at least, unless you are using low voltage programming. |
|
|
rwyoung
Joined: 12 Nov 2003 Posts: 563 Location: Lawrence, KS USA
|
|
Posted: Tue May 04, 2004 8:20 am |
|
|
The PIC16F877A can't use a crystal faster than 20MHz. Your crystal might really be a 4MHz. I've seen some 4MHz cases marked as 4.0 and maybe the decimal point isn't too clear or just looks like dirt to your eyes
Check the oscillator operation with an oscilloscope (100MHz bandwith at least) and x10 probe (so you don't load down the pins so much they oscillator stops).
And like Halpo said, use the #fuse statement. I think that statement has caused more problems for people because they skipped it or misunderstood what the settings should be. _________________ Rob Young
The Screw-Up Fairy may just visit you but he has crashed on my couch for the last month! |
|
|
Vlad
Joined: 03 May 2004 Posts: 8
|
|
Posted: Tue May 04, 2004 8:35 am |
|
|
Thanks guys. That must be it... From what I recall on one of the boards from Microchip, you can select between the internal and external clock (crystal). Is that correct ?
Anyway, I am curious why would changing the timer overflow with set_timer1(N) not change the time between the interrupts ?
Thanks for the help,
Vlad |
|
|
Vlad
Joined: 03 May 2004 Posts: 8
|
|
Posted: Tue May 04, 2004 8:43 am |
|
|
I just looked at the crystal, and its clearly 40MHz. I got this board from a friend who was using it for PIC18 chips, so it might as well be too fast for my PIC16. I guess I will see if he has slower crystal. |
|
|
Vlad
Joined: 03 May 2004 Posts: 8
|
|
Posted: Tue May 04, 2004 9:14 am |
|
|
Put the 4MHz crystal in, but still no change with different overflows... I am going to try timer0, just in case. |
|
|
Vlad
Joined: 03 May 2004 Posts: 8
|
|
Posted: Tue May 04, 2004 9:50 am |
|
|
Same problem with Timer0.
Code: |
#include <16F877A.h>
#device ICD=TRUE
#device adc=8
#use delay(clock=4000000)
#include "math.h"
#fuses NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
//--- from main ---
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_counters(RTCC_INTERNAL,RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
//-------------
delay_ms(30);
LCD_Init();
//-------------
LCD_Data();
LCD_Setup_Digits();
counter=0; // ms counter
setup_timer_0(T1_EXTERNAL | T1_DIV_BY_1);
set_timer0(2);
enable_interrupts(INT_TIMER0);
while(input(SW1)==1){}
enable_interrupts(GLOBAL);
while(input(SW2)==1){}
//---------
#int_timer0
void timer0_isr()
{
counter++ ;
if(flag)
{ output_low(PIN_B7);
flag=0;
}
else
{ output_high(PIN_B7);
flag=1;
}
set_timer0(2);
}
|
|
|
|
Ttelmah Guest
|
|
Posted: Tue May 04, 2004 10:47 am |
|
|
General comment.
You _will not_ get accuracy, setting a timer to a value inside an ISR. Unfortunately, it takes time to get to the end of the ISR routine, and the time taken, depends on the path taken through the ISR. Hence when you set the timer to a value, you will generate timing errors. You really must leave the timer to free-run, and handle the timing 'tweaks' by adjusting the counter, rather than the timer value.
Either choose a cystal value, that gives a precise division to mSec steps in the interrupt, or accept that the steps will not be in mSec, but use a counter that increments using a binary multiple of the division factor required, and then scale the result to display mSec. The error from this will be small, and will be repeatable, so won't matter for a timing application.
You don't show your declaration of 'counter'. Remember this will have to be a long, and probably an int32, and will need to be printed as such.
Remember you need to disable the interrupt as soon as the falling edge is seen on the switch, or the code will keep counting, which can lead to 'silly' numbers if it changes between digits being displayed.
mSec accuracy, is 'pushing it'. You can do this with a 40MHz crystal, but at a slower cyrstal rate, the time taken in the interrupt itself will easily be _large_ relative to this sort of timing accuracy. Personally, I'd aim for 1/100th second, rather than mSec counting (this is all that is required for most professional racing...).
Best Wishes |
|
|
|