|
|
View previous topic :: View next topic |
Author |
Message |
Alex Guest
|
Time problem |
Posted: Tue Oct 05, 2004 6:21 am |
|
|
I am trying to Transmit one frame every 1min 10 times using PIC16F877, Timer2 - interrupt every 1ms.
From time to time the minute time becomes less and less.
In other words first time it is a minute, 2nd 57sec, 3rd 50Sec and so on.
How to get the exact 1 minute every time? Thank you
while(1)
{
switch(MAIN_STATES)
{
case FIRST_STATE:
{
if (!TxTimeOut)
{
TxFrame(PING_CMD);
MAIN_STATES = SECOND_STATE;
break;}
//-----------------------------------------------------------
case SECOND_STATE:
{
ClearTime();
MAIN_STATES = THIRD_STATE ;
break;}
//-----------------------------------------------------------
case THIRD_STATE:
{
if (Minutes == 1)
{
FIRST_STATES = Tx_STATE ;
if (++TxTimes == 6)
TxTimeOut = 1 ;
}
break;}
}
//-----------------------------------------------------------
void ClearTime(void)
{
One_ms = 0 ;
Hund_mS = 0 ;
Seconds = 0 ;
Minutes = 0 ;
Hours = 0 ;
tmr2 = 0 ;
}
//-----------------------------------------------------------
#INT_TIMER2 //Interrupt every 1mS
void timer2_isr(void)
{
//Count 100mS
if (++One_ms >= 99)
{
One_ms = 0 ;
Hund_mS ++ ;
}
//Count Seconds
if (Hund_mS >= 9)
{
Hund_mS = 0 ;
Seconds ++ ;
}
//Count minutes
if (Seconds >=59)
{
Seconds = 0 ;
Minutes ++ ;
}
//Count Hours
if (Minutes >= 59)
{
Minutes = 0 ;
Hours ++ ;
}
} |
|
|
Ttelmah Guest
|
Re: Time problem |
Posted: Tue Oct 05, 2004 7:00 am |
|
|
One obvious comment, is not to clear the mSec counter.
You don't show how long the transmission takes, but assuming this is a normal 'serial' link at perhaps 9600bps, then several mSec will have passed when you reach this point. Hence your counter will now be in error by the amount it has already advanced. Instead let it run continuously, and only clear the slow counters. Generally, to get accurate times, the clock should be independant of other events in the code.
This however would lead to the timing being slow, rather than fast. You don't show the programming used to give the 1mSec 'tick', and it would be worth 'triple checking' these calculations (the CCS 'wizard', often used to miscalculate the timings).
The counting, would appear to be slightly in error, and this could be partially to blame. On the mSec counter, this is incremented before testing. Hence the sequence would be:
99 -> 0,1,2, ...... 98, 99 -> 0.
This gives only 99 actual 'counts in the loop, not the 100 that are actually required, which will lead to the clock running fast.
My feeling is that the code is actually running fast because of the count error, and this is sometimes being partially compensated for, by the latter 'clear'.
Best Wishes |
|
|
alexz
Joined: 17 Sep 2004 Posts: 133 Location: UK
|
|
Posted: Tue Oct 05, 2004 7:10 am |
|
|
But I clear the timer after transmitting(19200 Boud rate)
So I think the transmision time should not afect should it?
The mS counter :
The timer is initialized to 16 prescaler and PR2= 249 ; //1mS
So 16uS*249 = 1mS _________________ Alex |
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Tue Oct 05, 2004 8:37 am |
|
|
What frequency is your crystal? Could you show your timer setup? Ttelmah is correct in that you are incrementing your counters 1 count too soon. Try:
Code: |
#INT_TIMER2 //Interrupt every 1mS
void timer2_isr(void)
{
if (++One_ms >= 100) //Count 100mS
{
One_ms = 0 ;
if (Hund_mS >= 10) //Count Seconds
{
Hund_mS = 0 ;
if (Seconds >= 60) //Count minutes
{
Seconds = 0 ;
if (Minutes >= 60) //Count Hours
{
Minutes = 0 ;
if(++Hours >= ??)// and so forth
{
}
}
}
}
}
}
|
This makes it so that the next if() is only looked at if needed. Your code looks at every if() every time which will slow the ISR down a bit.
Ronald |
|
|
|
|
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
|