Полная версия этой страницы:
Отстает секундомер
LexRoss
Oct 23 2010, 08:34
Отстает секундомер на 2 минуты за полчаса. И в протеусе и в железе примерно так же. Резонатор керамический 1 МГц, ATmega8L. Компилятор WinAvr. Что не так?
Код
#include <avr/io.h>
#define F_CPU 1000000
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include <stdlib.h>
#include <lcd_lib.h>
#include <lcd_lib.c>
#include <avr/signal.h>
unsigned int counter; // счетчик для секундомера: 488 прерываний = 1 секунда
unsigned char sec,minut,hour; // сек.,мин.,часы для секундомера
unsigned char c[5];
ISR(TIMER0_OVF_vect)
{
counter++;
if (counter==488)
{
Lcd_Goto(0,0);
Lcd_WriteData('t');
Lcd_WriteData('i');
Lcd_WriteData('m');
Lcd_WriteData('e');
Lcd_WriteData(' ');
itoa(hour,c,10);
if (hour<10)
{
Lcd_WriteData('0');
Lcd_WriteData(c[0]);
}
else
{
Lcd_WriteData(c[0]);
Lcd_WriteData(c[1]);
}
Lcd_WriteData(':');
itoa(minut,c,10);
if (minut<10)
{
Lcd_WriteData('0');
Lcd_WriteData(c[0]);
}
else
{
Lcd_WriteData(c[0]);
Lcd_WriteData(c[1]);
}
Lcd_WriteData(':');
itoa(sec,c,10);
if (sec<10)
{
Lcd_WriteData('0');
Lcd_WriteData(c[0]);
}
else
{
Lcd_WriteData(c[0]);
Lcd_WriteData(c[1]);
}
Lcd_WriteData(' ');
Lcd_WriteData(' ');
Lcd_WriteData(' ');
counter=0;
sec++;
if (sec==60)
{
sec=0;
minut++;
if (minut==60)
{
minut=0;
hour++;
}
}
}
}
int main (void) {
Lcd_Init();
DDRD = 0b00000001;
sei();
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
TCCR0=0x02;
TCNT0=0x00;
TIMSK=0b00000001; // разреш. прерыв. timer0
while (1)
{
}
return 0;
}
kolobok0
Oct 23 2010, 08:43
Цитата(LexRoss @ Oct 23 2010, 12:34)

Отстает секундомер на 2 минуты за полчаса. ...
Код
....
ISR(TIMER0_OVF_vect)
{
....
Lcd_Goto(0,0);
Lcd_WriteData('t');
Lcd_WriteData('i');
Lcd_WriteData('m');
....
Загляните в функции вывода на дисплей.
Там увидите либо задержку либо опрос готовности.
Как вы думаете
а) зачем это сделано?
б) сколько это занимает времени?
(круглый)
ЗЫ
Прерывания (особенно железные) - это как выстрел. откидал регистры и забыл(С)
Исключение составляет когда программа сделана по принципу переключения логики. основной код, прерываем - логически переключаемся на другую тему, возвращаемся к нормальному циклу...(надеюсь не сумбурно пояснил исключение

)
Цитата(LexRoss @ Oct 23 2010, 12:34)

Что не так?
Вероятно, слишком долгое выполнение процедуры прерывания от таймера: вызов всех процедур работы с экраном столь долог, что пропускаются часть прерываний. У Вас бесконечный цикл в main пустой - почему бы не вынести из прерывания в этот цикл вывод на экран.
Vasily_
Oct 23 2010, 08:53
Секундомер на керамическом резонаторе? забавно! а что кварц нормальный поставить нельзя?
DpInRock
Oct 23 2010, 08:56
И когда вынесите процедуру вывода на экран наружу, установите часы минуты секунды как volatile.
Ну, естественно, вывод - по отдельному флагу, тоже volatile. Т.е. некая переменная, которая устанавливается, когда меняется счетчик секунд. В майне вы ея опять в ноль будуте устанавливать после вывода.
LexRoss
Oct 23 2010, 09:17
Вынес вывод на экран в main. Вроде лучше стало.
Керамический резонатор, т.к. другого не нашел. Питание от батарейки, поэтому 1мгц.
Цитата
И когда вынесите процедуру вывода на экран наружу, установите часы минуты секунды как volatile.
Зачем volatile ?
Цитата
Ну, естественно, вывод - по отдельному флагу, тоже volatile. Т.е. некая переменная, которая устанавливается, когда меняется счетчик секунд. В майне вы ея опять в ноль будуте устанавливать после вывода.
Ничего не понял

Теперь даже спешат немного. За полчаса на 15сек.
DpInRock
Oct 23 2010, 10:00
Ну, вообще-то математика доступная.
Резонатор 0.5% точности. 0.2% температурной нестабильности. Еще вы конденсаторами его придавили. Предположим, 1%
Полчаса = 1800 сек. 1% = 18 секунд.
А про volatile - рекомендую почитать на форуме. Очень полезная вещь.
kolobok0
Oct 23 2010, 10:01
Цитата(LexRoss @ Oct 23 2010, 13:17)

..Теперь даже спешат немного. За полчаса на 15сек.
это уже похоже на резонатор(ставте кварц, нафик вам гимор то?) либо чистоту кода (ну там всякие блокировки прерываний не вовремя и прочая шняга).
(круглый)
demiurg_spb
Oct 23 2010, 11:09
Цитата(DpInRock @ Oct 23 2010, 14:00)

А про volatile - рекомендую почитать на форуме. Очень полезная вещь.
Даже больше - необходимая!
chief_olimp
Oct 23 2010, 13:08
Цитата(LexRoss @ Oct 23 2010, 12:17)

Питание от батарейки, поэтому 1мгц.
Дело в том, что 1 Мгц не совсем хороший кварц для этих целей. Чаще используют кварцы 1.8432, 2.4576, 3.2768 ... На таких кварцах отсутствует погрешнось в временных диапазонах. Ну неточность и температурный дрейф не в счет. Ну или программную коррекцию вводите.
ILYAUL
Oct 23 2010, 13:56
Почему бы просто не задействоать асинхронный таймер с 32,768 Кгц если уж стоит задача СЕКУНДОМЕР
LexRoss
Oct 23 2010, 14:41
Цитата(ILYAUL @ Oct 23 2010, 17:56)

Почему бы просто не задействоать асинхронный таймер с 32,768 Кгц если уж стоит задача СЕКУНДОМЕР
На самом деле будет велокомпьютер. 32,768 в данном случае мало.
Сейчас положу в холодильник, посмотрю как будет плавать от температуры, если не сильно, то программно подкорректирую.
Ваши часы шли бы точнее, если бы вы нормально запрограммировали таймер на 1-секундный период, а не гоняли его по полтыщи раз в холостую, каждый раз вызывая тормозное прерывание.
сначала измените программу - в прерывании таймера 3 вызова itoa (мягко говоря небыстрой функции) и куча обращений к LCD. Вынесите все это в основной цикл. Заведите переменную - флаг обновления LCD, в прерывании пишите туда 1, в основном цикле проверяйте это значение, спокойно обновляйте индикацию и переходите в Sleep.
Еще - обновлять индикацию нужно после инкремента секунд-минут а не перед этим.
ILYAUL
Oct 23 2010, 15:07
Цитата(LexRoss @ Oct 23 2010, 18:41)

32,768 в данном случае мало.
Не понял , как так может быть , что вдруг для секундомера стало мало часового кварца ?
LexRoss
Oct 23 2010, 15:48
Цитата(ILYAUL @ Oct 23 2010, 19:07)

Не понял , как так может быть , что вдруг для секундомера стало мало часового кварца ?
У меня на этом таймере еще куча всего будет.
В холодильнике убежали еще на +5 секунд, т.е. 20 сек за полчаса. Для меня достаточно, скорректирую программно.
Кстати, думал,что контрастность дисплея (WH1602) упадет в холоде, а он так же показывает, тормозит только немного.
ILYAUL
Oct 23 2010, 16:29
Посчитал:
Только 16 битный таймер при прескалере 16-64 не даст ошибки деления - OCR сработает ровно через секунду
А вот 8 битному - не реально работать без ошибки
DpInRock
Oct 23 2010, 16:32
Поставьте кварц - ЛЮБОЙ - и не канифольте себе мозг.
Токо конденсаторы поставьте согласно даташита. Чтоб совсем уж точно было.
Но для велосекундомера - это совершенно не критично. Для часов - критично.
Цитата
Но для велосекундомера - это совершенно не критично.
тогда и резонатор не нужен - хватит и внутреннего генератора
DpInRock
Oct 23 2010, 16:54
Вы тоже мозг не канифольте, а посмотрите на стабильность и точность внутреннего генератора.
Просто запомните, что источником времени, когда важны секунды может быть только кварц.
Если проблемы с потреблением - ставьте маленький кварц. Если совсем офигенные проблемы с потреблением - ставьте timekeeper какой-нибудь. У многих есть источник прерываний секундных импульсов.
Но полагаю, для спортивного секундомера разрешающая способность 1 секунда - отстой. Посему -
СТАВЬТЕ КВАРЦ какой найдете. У вас дома кварцов - минимум десяток. Токо внимательно оглянитесь по сторонам.
LexRoss
Oct 23 2010, 17:33
Кварц есть только на 4Мгц, причем потребление с ним возрастает больше чем в 2 раза. Мне и с керамическим нормально. Спасибо всем за советы.
Цитата(LexRoss @ Oct 23 2010, 20:33)

Кварц есть только на 4Мгц, причем потребление с ним возрастает больше чем в 2 раза. Мне и с керамическим нормально. Спасибо всем за советы.
Кварц из любого будильника... на таймер2 в асинхронном режиме. Сам котроллер включить от 1мгц внутреннего РЦ.
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.