View previous topic :: View next topic |
Author |
Message |
Flavio58
Joined: 08 Sep 2003 Posts: 21
|
TIMER1 too slow |
Posted: Mon Sep 08, 2003 8:56 am |
|
|
I have activated a timer1 connected at a 32Khz oscillator to manage the date/time in my project.
The function to manage the overflow is this
#int_timer1
void clock_isr()
{
if(--int_count==0) {
++seconds;
int_count=INTS_PER_SECOND;
}
}
and this is the init procedure in the main funtion...
T1CON = 0x8F;
PIE1 = 1;
set_timer1(0x00);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
The T1CON value 0x8F set the prescaler to 1:1 and set the bits to activate the timer1.
The interrupt routine work ....but the problem is that TIMER1 call the overflow interrupt only 1 time every 2 seconds....
I tried to change the overflow value to 8 bits but the result is the same ....
There are some strange init procedure to activate this timer ? |
|
|
ttelmah Guest
|
Re: TIMER1 too slow |
Posted: Mon Sep 08, 2003 9:49 am |
|
|
Flavio58 wrote: | I have activated a timer1 connected at a 32Khz oscillator to manage the date/time in my project.
The function to manage the overflow is this
#int_timer1
void clock_isr()
{
if(--int_count==0) {
++seconds;
int_count=INTS_PER_SECOND;
}
}
and this is the init procedure in the main funtion...
T1CON = 0x8F;
PIE1 = 1;
set_timer1(0x00);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
The T1CON value 0x8F set the prescaler to 1:1 and set the bits to activate the timer1.
The interrupt routine work ....but the problem is that TIMER1 call the overflow interrupt only 1 time every 2 seconds....
I tried to change the overflow value to 8 bits but the result is the same ....
There are some strange init procedure to activate this timer ? |
I'm suprised it is this fast...
1) Why not use the internal setup functions, rather than going 'DIY'. It makes the code more readable, and more likely to work on different chips.
2) I presume from your description, that you have an external clock input, at 32768Hz, rather than the master oscillator running at this speed?. Otherwise I'd expect the timer to interrupt every eight seconds, since there is an /4 division automatically in place from the master clock.
3) Say what PIC is involved?. The use of the high bit in T1CON, suggests one of the 18F family, but it would be nice to know...
Now assuming I am right on the above, then your behaviour is exactly what you'd expect. The timer counts from 0 to 65536, which takes 2 seconds given a 32768Hz clock.
You then talk about 'changing the overflow value to 8 bits'. As far as I know, there is no such ability on this timer, on any PIC I can think of. There is an ability to switch the read/write mode between 8 bits and 16 bits, but the timer still counts to 65536.
If you want to have an interrupt at one second, then you will need to use the CCP module as well. If you set this to reset Timer1, when the count reaches 32768, then the CCP interrupt can be used at one per second.
Timer2, is capable of giving one/second interrupt from the same clock rate (set the prescaler to /128).
Best Wishes |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
Real Time Keeping |
Posted: Mon Sep 08, 2003 12:13 pm |
|
|
Funny you should mention this. I posted some code just before the forum was moved. The code you posted is not going to work accuratly using the system clock because you round the number of ints per second. Try something like this. The variable Ticker is the number of instruction cycles remaining until the second count is incremented. During each interupt, decrement ticker by the number of instruction cycles per timer interupt. If Ticker is less than the number of instructions per interupt, increment seconds and add instruction cycles per second to ticker. This will be as reliable as using an extra crystle for keeping time. Long term accuracy is as good as the crystle. If a crystle has +-10PPM you could be off by 10 seconds in about 11.5 days. This also allows the code in main to check for flags that are set at regular intervals.
int1 Initialized=1;
int1 Clock_mS_Tic;
int1 Clock_S_Tic;
int32 Ticker;
#locate Ticker = 0x020
int8 Ticker_byte_2;
#locate Ticker_byte_2 = 0x022
Int32 Seconds;
#inline
void Initialize_RTC(void);
/********************************************************************
* Initialize RTC *
********************************************************************/
#inline
void Initialize_RTC(void)
{ Ticker = 19660800;
setup_timer_2 ( T2_DIV_BY_4, 0xff, 1 );
enable_interrupts( INT_TIMER2 );
}
/********************************************************************
* Service RTC *
********************************************************************/
#int_TIMER2
void TIMER2_isr()
{ Clock_mS_Tic=1;
if(--Ticker_byte_2)
{ Ticker+=19660800;
Seconds++;
Clock_S_Tic=1;
}
} |
|
|
regan
Joined: 10 Sep 2003 Posts: 5 Location: Wellington, New Zealand
|
Keeping it Real |
Posted: Wed Sep 10, 2003 3:46 am |
|
|
To use Timer1 with a 32KHz crystal to get 1 second interrupts use the following code:
#define clk_reload 0x8000
// to setup the timer use:
void clk_init()
{
setup_timer_1(T1_CLK_OUT|T1_EXTERNAL|T1_DIV_BY_1);
set_timer1(clk_reload);
enable_interrupts(INT_TIMER1); // assuming INT_GLOBAL already enabled
}
// and the interrupt handler can be:
#int_timer1
void clk_isr()
{
set_timer1(clk_reload);
// put your code here.
}
regan. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Wed Sep 10, 2003 6:10 am |
|
|
It is better to add your reload time to the timer1 value to account for any latencies. |
|
|
|