2014-10-11 4 views
0

Я пытаюсь сделать часы на Atmega8. У меня есть 8Mhz кварц.Часы на Atmega8

Я использую timer0 прерывания тактовых 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; 
} 

Проблема заключается в том, что мои часы бегущий слишком быстро или слишком медленно.

Рассчитанное значение, которое я положил в регистр TCNT0, равно 80, но в этом случае часы работают слишком медленно. Когда я использую 80-4, часы также работают слишком медленно. Когда я использую 80-5, это слишком быстро.

Я не знаю, как это могло быть ???

UPDATE: Теперь настройки следующие, но проблема все еще существует.

/* 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; 
} 
+0

Сколько стоит «слишком быстро»? Сколько секунд в час, например? У вас есть осциллограф? –

+0

Около 5 минут в 3 часа. Нет, у меня нет осциллографа. – vitperov

ответ

1

Первый выпуск очевиден, частота 8MHz/1024 = 7812,5 Гц, то есть с использованием 80 не имеет смысла. Манипулирование TCNT0 также является проблемой, поскольку есть некоторая задержка, так как счетчик достиг нулевого уровня и выполняется прерывание, а поток кода достигает последней команды. Третья - частота кристалла, вы уверены, что это действительно 8 МГц? Поскольку неэффективная емкостная нагрузка или просто сдвиг частоты могут привести к ошибке синхронизации.

+0

Спасибо! Я исправляю частотный devider и перемещаю 'TCNT0 - = TMR_RELOAD' в начало функции прерывания. После нескольких часов мы увидим, помогает ли это. Спасибо! – vitperov

2

Обратите внимание, что при вызове

TCNT0 -= TMR_RELOAD; 

регистр TCNT0 уже равен 0. Таким образом, вы получаете TCNT0 = 131, который требует 124 тиков переполнения. Это означает, что ваши часы

1/31250 * 250 = 8ms

быстрее в секунду, что приводит к

8ms * 60 х 60 х3 = 86.4s

за 3 часа. Это не те 5 минут, которые вы упомянули в комментариях, но ошибка есть. Существует потенциально некоторая дополнительная ошибка, исходящая от вашего 8-мегагерцового кристалла. Это зависит от качества кристалла и того, насколько хорошо разработан ваш резонансный контур.

Я бы посоветовал вам использовать прерывание выходного сравнения Timer2 вместо использования прерывания переполнения и перезагрузки значения TCNT.

«Выход сравнения Регистр содержит 8-битное значение, которое непрерывно сравнивается со значением счетчика (TCNT2). Совпадение может быть использован для генерации выходного сигнала сравнения прерывания ...»

Его легче обрабатывать, и вам не нужно иметь дело с «перезагрузкой» таймера.

Вы также можете рассмотреть возможность использования кристалла часов с частотой 32,768 кГц.

+0

1) Прерывание происходит с частотой 250 Гц. 1/250 = 4 мс. Число 125 тиков TMR0 => 1 дополнительное количество TMR0 = 4ms/125 = 32 uS. 32 uS * 60 * 60 = 115,2 мс в час. Или 0,35 с в течение 3 часов. ------- 2) «Выходной регистр сравнения содержит 8-битовое значение, которое непрерывно сравнивается со значением счетчика (TCNT2). Соответствие может быть использовано для генерации прерывания сравнения выходных данных ...» Чтобы иметь ** пользовательские интервалы времени ** перед прерываниями, вам все равно нужно загрузить новое значение в TCNT2. – vitperov

+0

3) Сегодня я заметил большую задержку, когда я был вне моей квартиры (4 часа в 10 часов). Возможно, это также проблемы с электропитанием. 4) ** Спасибо за помощь! ** – vitperov

+0

@vitperov: Хм. Регистр TCNT0 имеет значение 1 «галочка» (1/31250 = 32us), если он учитывает только 124 вместо 125. Так как вы считаете 250 до завершения второй, вы получаете 250 * 32us в секунду -> 8 мс. Или я чего-то не хватает? –