Easyelectronics.ru

Электроника для всех
Текущее время: 21 янв 2019, 19:09

Часовой пояс: UTC + 5 часов




Начать новую тему Ответить на тему  [ Сообщений: 6 ] 
Автор Сообщение
 Заголовок сообщения: Считать время по пройденным миллисекундам.
СообщениеДобавлено: 04 дек 2017, 14:45 
Старожил

Зарегистрирован: 17 фев 2016, 17:31
Сообщения: 216
В системе нет RTC.
Я подумал сделать так. В начале логирования я ввожу стартовое реальное время и включаю счетчик миллисекунд.
Во время логирования, помимо данных, я сохраняю временную метку - пройденные миллисекунды.
И в конце логирования я могу вычислить реальное время по пройденным милисекундам.
Код:
uint32_t MillisecsToSeconds (uint32_t millisecs)
{
    return ( millisecs / 1000);
}

uint32_t MillisecsToMinutes (uint32_t millisecs)
{
    return ( millisecs / 60000); 
}

uint32_t MillisecsToHours (uint32_t millisecs)
{
    return ( millisecs / 3600000);   
}

uint32_t MillisecsToDays (uint32_t millisecs)
{
    return ( millisecs / 86400000);   
}

void ElapsedDate(sRTC start_date, uint32_t millisecs, sRTC *elapsed_date)
{
    elapsed_date->rtcSec = start_date.rtcSec + MillisecsToSeconds(millisecs)
    elapsed_date->rtcMin = start_date.rtcMin + MillisecsToMinutes(millisecs);
    elapsed_date->rtcHour = start_date.rtcHour + MillisecsToHours(millisecs);
    elapsed_date->rtcDay = start_date.rtcDay + MillisecsToDays(millisecs);
}


Но потом я заметил что функция не учитывает переполнение секунд, минут, дней. И вот тут я туплю - как оптимальней это сделать?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Считать время по пройденным миллисекундам.
СообщениеДобавлено: 04 дек 2017, 15:06 
Старожил

Зарегистрирован: 16 ноя 2012, 07:47
Сообщения: 2734
Например так:
Код:
#define JD0                  2451911         // дней до 01 янв 2001 ПН

typedef struct {
         uint8_t      Sec;            //Секунды
         uint8_t      Min;            //Минуты
         uint8_t      Hours;            //Часы
         uint8_t      Day;            //День недели (1-7)
         uint8_t      Date;            //День
         uint8_t      Month;            //Месяц
         uint8_t      Year;            //Год
         int8_t      Temp_Int;         //Температура (целая часть) (-127-127)
         uint8_t      Temp_Fract;         //Дробная часть (0-3), каждая единица - 0.25°С
   List_RTC_Stat      Status;            //Статус часов
} _RTC_DATA_STRUCT;

uint32_t   TimeToCounter(_RTC_DATA_STRUCT * ftime)
{
   uint32_t   JDN;
   uint16_t   y;
   uint8_t      m, a;

   // Вычисление необходимых коэффициентов
   a = (14 - ftime->Month)/12;
   y = ftime->Year +2000 + 4800 - a;            //2000 т.к. у нас дата идет от 0 до 99
   m = ftime->Month + (12*a) - 3;
   // Вычисляем значение текущего Юлианского дня
   JDN = ftime->Date;
   JDN+= (153*m + 2)/5;
   JDN+= 365*y;
   JDN+= y/4;
   JDN+= -y/100;
   JDN+= y/400;
   JDN-= 32045;
   JDN-= JD0;                              // так как счетчик у нас нерезиновый, уберем дни которые прошли до 01 янв 2001
   JDN*= 86400;                           // переводим дни в секунды
   JDN+= (ftime->Hours*3600);                  // и дополняем его секундами текущего дня
   JDN+= (ftime->Min*60);
   JDN+= (ftime->Sec);
   // итого имеем количество секунд с 00-00 01 янв 2001
   return JDN;
}
void   CounterToTime(uint32_t counter,_RTC_DATA_STRUCT* ftime)
{
   uint32_t ace;
   uint8_t b,d,m;

   ace = (counter/86400) + 32044 + JD0;
   b = (4*ace + 3)/146097;
   ace = ace - ((146097*b)/4);
   d = (4*ace + 3)/1461;
   ace = ace - ((1461*d)/4);
   m = (5*ace + 2)/153;

   ftime->Date = ace - ((153*m+2)/5) + 1;
   ftime->Month = m + 3 - (12*(m/10));
   ftime->Year = 100*b + d-4800 + (m/10) - 2000;
   ftime->Hours = (counter/3600)%24;
   ftime->Min = (counter/60)%60;
   ftime->Sec = (counter%60);
}

Сначала инициализируем счетчик через TimeToCounter, затем берем текущую дату/время через CounterToTime. Счетчика секунд uin32_t хватит на 100+ лет. Вам надо лишь мс добавить.
У себя использую вместе с RTC для замера продолжительности процесса, что-то вроде:
Инициализация счетчика (стартовое время процесса)
Код:
FirstStdData.StartTimeSec   = TimeToCounter(&RTC_Data);   // Текущее время - время старта

Код:
         if ( AutoWorkData.Stat != AUTO_WORK_MODE_STOP )   // автоматика работает
         {
            // Прошло времени
            uint32_t temp = TimeToCounter(&RTC_Data) - FirstStdData.StartTimeSec;
            FirstStdData.ExpTime.Hours   = (temp/3600);
            FirstStdData.ExpTime.Min   = (temp/60)%60;
            FirstStdData.ExpTime.Sec   = (temp%60);

            hItem = WM_GetDialogItem(pMsg->hWin, ID_TEXT_2);
            sprintf((char *)TempBuf, "%02u:%02u:%02u",FirstStdData.ExpTime.Hours,FirstStdData.ExpTime.Min,FirstStdData.ExpTime.Sec);
            TEXT_SetText(hItem, (char const *)TempBuf);
         }

Т.к. счетчик берет отсчет с 2001 года, можно не боятся отрицательной суммы, разница всегда положительная.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Считать время по пройденным миллисекундам.
СообщениеДобавлено: 04 дек 2017, 15:54 
Старожил

Зарегистрирован: 17 фев 2016, 17:31
Сообщения: 216
Hold писал(а):
Например так:

спасибо.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Считать время по пройденным миллисекундам.
СообщениеДобавлено: 04 дек 2017, 18:11 
Старожил
Аватара пользователя

Зарегистрирован: 14 апр 2014, 11:06
Сообщения: 1442
Откуда: Курск
Сделайте на юникстайм. Один счётчик. Никаких переполнений


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Считать время по пройденным миллисекундам.
СообщениеДобавлено: 04 дек 2017, 18:51 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 2723
Операции деления для каждой единицы измерения будут занимать немало времени, особенно если нет аппаратного делителя.
Вычислять единицу "год" в системе без резервного батарейного питания - практически никогда не пригодится.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Считать время по пройденным миллисекундам.
СообщениеДобавлено: 05 дек 2017, 11:36 
Старожил

Зарегистрирован: 16 ноя 2012, 07:47
Сообщения: 2734
Ну, если у автора не F0, где нет аппаратного деления, то деление и остаток деления все же целочисленные операции и выполняются быстро.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 6 ] 

Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: woroba


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB