Решил на старости лет познакомиться с микроконтроллерами.
Задумал сделать часы в свою девятку. Нашел мегу48, покурил данный славный сайт, даташит конечно, книжки.
Написал программу часов - термометра, не всю конечно сам, огромный респект и уважуха авторам, делящимся своими разработками (Danko в частности), вытравил плату, запаял, сделал программатор по своей схеме, чтобы не скучно было
Работает, ура!
Поставил в автомобиль и приступил к лётным испытаниям.
Результат плачевный - часы отстают примерно на 2 минуты в сутки. Ужос.
Тактирую от кварца 4 МГц, конденсаторы 22 pF, кварц менял на 8 Мгц, визуально идут в 2 раза быстрее (проверил корректность установки Fuse bits), точность с 8 МГц кварцом не проверял. Пробовал установить другой кварц на 4 МГц, тоже отстают на те же пару минут.
Поправил режим таймера 1 с Normal на CTC, не помогло.
Продраил плату зубной щёткой со спиртом - результат тот же, лучше бы выпил с горя
Тикают часы в прерывании таймера 1
Его код инициализации:
Код: Выделить всё
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 62,500 kHz
// Mode: CTC top=OCR1A
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x0B;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x02;
OCR1AL=0x71;
OCR1BH=0x00;
OCR1BL=0x00;
Код: Выделить всё
// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void) //Прерывание происходит с частотой 62500 Гц / 625(0x271) = 100 раз в сек
{
// TCNT1H=0x00;
// TCNT1L=0x00;
milliseconds++;
// PORTC.4 = 1;
if (milliseconds >= 100 ) { milliseconds = 0; seconds++; }
if (seconds >= 10) { seconds = 0; ten_seconds++; }
if (ten_seconds >= 6) { ten_seconds = 0; minutes++; ign_sens=1; }
if (minutes >= 10) { minutes = 0; ten_minutes++; }
if (ten_minutes >= 6) { ten_minutes = 0; hours++; }
if (hours >= 10) { hours = 0; ten_hours++; }
if (ten_hours >= 2 && hours == 4) { ten_hours = 0; hours = 0; }
// PORTC.4 = 0;
}
(вывод на индикаторы - семисегментные светодиодные), но это прерывание вроде не должно влиять на точность хода часов, или я не прав?
Больше прерываний нет. Есть еще запреты прерываний в процедуре опроса датчиков DS18B20, но я эти датчики пока не устанавливал, и они не опрашиваются.
Посчитал на калькуляторе процент погрешности часов, выяснил, что его можно скомпенсировать, уменьшив на единичку содержимое регистра OCR1A. Поставил вместо 0x271=625 значение 0x270=624.
Неделю часы идут практически секунда в секунду. Но ведь это вроде неверно! Нет мне покоя
Буду очень признателен за любое мнение по поводу - где могла порыться собака.
