Reputation: 1397
I am trying to do a clock on Atmega8. I have 8Mhz quartz.
I use timer0 interrupt for clock timeticks:
/* Settings */
#define TMR_RELOAD 80 - 5 /* 8 kHz / 80 = 100 Hz */
#define TMR_CNT_MAX 100 /* 1Hz internal counter */
/* internal variables */
static uint8_t tmr_cnt;
inline void TMR0_Init()
{
/* set clock source f_t0 = 8МHz/1024 = 8 kHz */
TCCR0 = _BV(CS00) | _BV(CS02);
TIMSK |= _BV(TOIE0); /* Enable TMR0 interrupt on overflow*/
}
ISR (TIMER0_OVF_vect)
{
if (tmr_cnt == 0)
Clock_Tick1s();
tmr_cnt++;
if (tmr_cnt >= TMR_CNT_MAX)
tmr_cnt = 0;
TCNT0 -= TMR_RELOAD;
}
The problem is that my clock a running too fast or too slow.
Calculated value that I put in TCNT0 register is 80, but in this case the clock is running too slow. When I use 80-4 the clock is also running too slow. When I use 80-5, it's too fast.
I don't know, how it could be???
UPDATE: Now settings are the following, but problem still exists.
/* Settings */
#define TMR_RELOAD 125 /* 31.25 kHz / 125 = 250 Hz */
#define TMR_CNT_MAX 250 /* 1Hz internal counter */
inline void TMR0_Init()
{
/* set clock source f_t0 = 8МHz/256 = 31.25 kHz */
TCCR0 = _BV(CS02);
TIMSK |= _BV(TOIE0); /* Enable TMR0 interrupt on overflow*/
}
ISR (TIMER0_OVF_vect)
{
TCNT0 -= TMR_RELOAD;
if (tmr_cnt == 0)
Clock_Tick1s();
tmr_cnt++;
if (tmr_cnt >= TMR_CNT_MAX)
tmr_cnt = 0;
}
Upvotes: 0
Views: 843
Reputation: 6092
Note that when you call
TCNT0 -= TMR_RELOAD;
the TCNT0 register already is 0. So you get TCNT0 = 131 which requires to 124 ticks to overflow. This means that your clock is
1/31250 * 250 = 8ms
faster per second, which results in
8ms * 60 x 60 x3 = 86.4s
per 3 hours. This is not the 5 minutes you mentioned in the comments but the error is there. There is potentially some additional error coming from your 8MHz crystal. This depends on the crystal quality and how well your resonant circuit is designed.
I would advice you to use the output compare interrupt of Timer2 instead of using an overflow interrupt and reloading the TCNT value.
"The Output Compare Register contains an 8-bit value that is continuously compared with the counter value (TCNT2). A match can be used to generate an Output Compare interrupt..."
Its easier to handle and you don't have to deal with "reloading" the timer.
You could also consider using a 32.768kHz clock crystal.
Upvotes: 2
Reputation: 833
The first issue is obvious, frequency is 8MHz/1024=7812.5 Hz, i.e. using 80 makes no sense. Manipulating TCNT0 is also problem because there is some delay since the counter has reached zero and interrupt is executed and code flow reaches last instruction. The third is frequency of crystal, are you sure that is really 8MHz? Because unproper capacitive load or just frequency shift may bring timing error.
Upvotes: 1