Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Часы
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
_Diman_
Раньше в прерывании было
Код
ISR(SIG_OVERFLOW2)
{
clock_++;
if (clock_==128)
    {                                                          
    clock_=0;
    hour[h_sek]++;
      }
}

Функция часов
Код
if (hour[h_sek]==60)
   {
       hour[h_sek] =0;
    hour[h_min]++;
….


Сделал
Код
ISR(SIG_OVERFLOW2)
{
clock_++;
if (clock_==128)
    {                                                          
    clock_=0;
    isr_1sek_=1;
      }
}


Код
void clock(void){
cli();    
  if ( isr_1sek_ )//прошла секунда
    {
       isr_1sek_=0;
    sei();
    if (++hour[h_sek]==60)
        {
        hour[h_sek] =0;
        hour[h_min]++;
        if (hour[h_min]==60)
….
sei();


Часы начали отставать. Не могу понять почему? Ведь событие происходит раз в секунду, пропустить его ни как нельзя, даже если программа зависнет на пол секунды, чего нет на самом деле. Вот, чешу репу, чего я не так сделал?
DpInRock
Насколько?

Что является эталоном? Случаем не виндовые часы?
_Diman_
Цитата(DpInRock @ Dec 8 2008, 00:08) *
Насколько?

Что является эталоном? Случаем не виндовые часы?


Примерно на 5 сек. в сутки. Тоже сначала показалось что что-то с комповскими часами не то, поэтому перед проверкой делал синхронизацию с временем интернета.
Раньше без коррекции в функции часов:
23:42 09.12.2007
0:20 14.12.2007 отстование 2 сек

Прикрепил исходник, но в нем наверное глухо разобраться (17kB)
rezident
_Diman_, я бы на вашем месте инкремент переменной делал после проверки условия на выход ее за границу допустимых значений, а не проверку условия после инкремента.
Код
if (hour[h_sec]<59)
  hour[h_sec]+=1;
else
  { hour[h_sec]=0;
    if (hour[h_min]<59)
      hour[h_min]+=1;
    esle
    { hour[h_min]=0;

Кроме этого переменная isr_1sek_ должна быть типа volatile.
Ну и вдобавок, если у вас структура времени, то может стоить оформить ее как структуру, а не простой массив значений.
P.S. исходник не смотрел laughing.gif
P.P.S. смущает строчка
Код
if (++hour[h_sek]==60)
. Я не настолько большой знаток стандартов Си, чтобы понять, что по стандарту раньше делается после индексирования и извлечения значения, инкремент значения или сравнение?
_Diman_
Я думаю тут не из-за этого, но можно и так.
Код
if (++hour[h_sek]>=60)


Инкремент после был бы:
Код
if (hour[h_sek]++==60)


На счет volatile, я смотрю листинг. Привык к WinAVR-20060421. Там обычно не прокатывает вот такое
Код
ISR(){
clock_--;
}

clock_=60;
while(clock_)


В функции часов, есть одно место "не очень" коррекция хода в час,
Код
if (++hour[h_min]==60)
{        
//cli();
if ( setup.corr_flag&BIT(fl_corr_znak_pl) )//корекция часов
    clock_+=setup.correction;//для убыстрения
    else
    clock_= 0x00-setup.correction;
//sei();

Но это раньше работало, здесь я тоже особых проблем не вижу.
Ладно, не буду голову забивать, буду разбираться в симуляторе.
DpInRock
Ошибка в программных счетчиках обычно дает какую-то определенную ошибку. Типа секунда в минуту и т.п.

Ошибка в инициализации таймера-делителя может давать намного меньшую ошибку.

Я тоже сравнивал уход относительно интернет часов. Плохо. Особенно на глаз. В течение пары минут отстает на пару секунд, потом догоняет. А виндовские с интернет часами - тоже не синхронно идут.

Тоже сейчас делаю ( как часть устройства) часы. Оставлял ровно на сутки. С интернет временем совпадает точно, пока страничка недолго висит на экране. Потом рассинхронизируется. Перегрузишь страничку - опять все точно...
777777
Я бы вообще все сделал в прерывании:
Код
ISR(SIG_OVERFLOW2)
{
if (++clock_==128)
    {
    clock_= 0;
    if(++hour[h_sek] == 60)
        {
        hour[h_sek] = 0;
        if(++hour[h_min] == 60)
            {
            hour[h_min] = 0;
            if(++hour[h_hour] == 24)
                {
                // ... и т.д.
                }
            }
        }
      }
}

Неужели несколько микросекунд нахлждения в прерывании так критичны?
_Diman_
Меня больше интересовало почему это случилось. А разве такое построение, с установкой флага в прерывании, не рабочие? По моему по барабану сколько пройдет времени до выполнения этой функции, главное чтоб было меньше секунды.
Если все делать в прерывании, то скорей всего яркость индикатора будет плавать на минимальном значении яркости, поэтому я не сделал так.
DpInRock
В прерывании, сначала решайте вопросы индикатора (и звука), а потом все остальные. Тогда время индикации будет постоянным.
Особенно это заметно, если звук по прерыванию генериться.
777777
Цитата(DpInRock @ Dec 11 2008, 07:03) *
В прерывании, сначала решайте вопросы индикатора (и звука), а потом все остальные. Тогда время индикации будет постоянным.

Обычно делают наоборот: фонвая программа занимается динамической индикацией и обработкой кнопок, так как для нее не критично изменение частоты на 10...20%, а все остальное делается в прерываниях.
Цитата(DpInRock @ Dec 11 2008, 07:03) *
Особенно это заметно, если звук по прерыванию генериться.

Не проще ли генерить его таймером?
_Diman_
Да как то уже все сделано, возвращаться неохота и нет времени.
Яркость тоже сидит в прерывании, всего их два, яркость и часы.
Звук примитивный пищит только, 1 таймером.
Вот писание часов http://startcd.narod.ru/clock/clock.html если интересно
только эти на ид10, а так они у меня с 2004 года уже трудятся.

Поменял коррекцию, не помогло.
Код
ISR(SIG_OVERFLOW0){
    if (++lcd_time_switch==light_isr)
        PORTLCD=lcd_buffer[znakomesto];
}
//**************************************
ISR(SIG_OVERFLOW2)
{
clock_++;
if (clock_==128)
    {                                                          
    clock_=correct;
    isr_1sek_=1;
      }
}

//**************************************
void clock(void){
  if ( isr_1sek_ )//прошла секунда
    {
    correct=0;
    if (++hour[h_sek]==60)
        {
        if (++hour[h_min]==60)
            {
            if ( setup.corr_flag&BIT(fl_corr_znak_pl) )//корекция часов
                correct=setup.correction;//для убыстрения
                else
                correct= 0x00-setup.correction;
            
            hour[h_min] =0;
            hour[h_hour]++;


Вообщем пока забросил.

Во блин, сейчас опять решил проверить уход, до синхронизации с интернетом за два дня секунд 13, после синхронизации 1 секунда. Получается у меня, что то с компом.
Извините, что ненароком мозги пудрил sad.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.