Главная » Статьи » Полезная информация |
Выполняя небольшой проект, столкнулся с необходимостью вести в устройстве подсчет количества пройденных суток. Время и дата брались с микросхемы DS1307, а сам период подсчета был небольшой (не больше 30 дней) и счетчик был организован на суммировании отработанных часов. Каждый час данные сохранялись в EEPROM на случай перебоя с питанием. И конечно же во время отсутствия питания часы не прибавлялись, что приводило бы к неточностям подсчета. В принципе все устраивало, так как питание устройства предусматривает наличие генератора, который запускается в течении пары минут. Но стало интересно как организовать программно расчет пройденного времени по разнице дат. Это сразу решило бы много проблем, в том числе и заморочки со стабильным питанием, да и ресурс EEPROM не безграничен. Результатом своей работы я и хочу сегодня поделиться с вами.
Алгоритм расчета строится на вычислении двух значений. Первое значение (Ds) - это количество дней между первой датой (когда запустили счетчик) и окончанием года. Второе значение (Dd) - количество дней от второй даты (когда проверяем счетчик) и окончанием года. Узнав эти значения мы легко можем высчитать разницу между датами (D). Для случая если даты находятся в одном году приведу поясняющую иллюстрацию. В случае же если даты относятся к разным годам значение Dd считается не от конца года, а от начала. И при необходимости добавляется количество дней смежных лет.
Итак, код для расчета ниже. Занимает в памяти около 1,5 кб и учитывает високосные годы (правда в упрощенном виде, считая високосными все года кратные четырём).
Dim D As Word 'количество пройденных дней
Dim Ds As Word 'вспомогательные переменные Dim Dd As Word Dim Dt As Byte Dim Dy As Byte Dim Dx As Byte Dim Nn As Byte Dim Dn As Word Dim Dm As Word Dim D0 As Byte 'число пуска Dim M0 As Byte 'месяц пуска Dim Y0 As Byte 'год пуска Dim D1 As Byte 'число проверки Dim M1 As Byte 'месяц проверки Dim Y1 As Byte 'год проверки 'значения переменных в качестве примера 'число/месяц/год запуска счетчика D0 = 1 M0 = 8 Y0 = 16 'число/месяц/год просмотра D1 = 2 M1 = 10 Y1 = 51 '///начало вычислений 'В цикле идет вычисление двух величин: 'Ds-оставшееся кол-во дней в году с момента запуска счетчика 'Dd-оставшееся кол-во дней в году от момента просмотра Do Incr Nn If Nn = 1 Then Dy = Y0 / 4 'вычисляем високосный год Dn = D0 Dm = M0 Elseif Nn = 2 Then Dy = Y1 / 4 Dn = D1 Dm = M1 End If Dy = Dy * 4 'если год поделился без остатка тогда он високосный If Dm = 1 Then Dd = 31 - Dn If Dy = Y1 Then 'если год високосный Dd = Dd + 335 Else Dd = Dd + 334 End If Elseif Dm = 2 Then If Dy = Y1 Then Dd = 29 - Dn Else Dd = 28 - Dn End If Dd = Dd + 306 Elseif Dm = 3 Then Dd = 31 - Dn Dd = Dd + 275 Elseif Dm = 4 Then Dd = 30 - Dn Dd = Dd + 245 Elseif Dm = 5 Then Dd = 31 - Dn Dd = Dd + 214 Elseif Dm = 6 Then Dd = 30 - Dn Dd = Dd + 184 Elseif Dm = 7 Then Dd = 31 - Dn Dd = Dd + 153 Elseif Dm = 8 Then Dd = 31 - Dn Dd = Dd + 122 Elseif Dm = 9 Then Dd = 30 - Dn Dd = Dd + 92 Elseif Dm = 10 Then Dd = 31 - Dn Dd = Dd + 61 Elseif Dm = 11 Then Dd = 30 - Dn Dd = Dd + 31 Elseif Dm = 12 Then Dd = 31 - Dn End If If Nn = 1 Then Ds = Dd End If Loop Until Nn = 2 Nn = 0 'вычисляем пройденные дни Dt = Y1 - Y0 'считаем сколько лет между запуском и проверкой If Dt = 0 Then 'если старт счетчика и проверка в одном году D = Ds - Dd Elseif Dt = 1 Then 'если разница один год If Dy = Y1 Then 'если год проверки високосный Dd = 366 - Dd Else Dd = 365 - Dd End If D = Ds + Dd Else 'если прошло больше одного года Dt = Y0 Incr Dt Do Dx = Dt / 4 'проверка високосного года Dx = Dx * 4 If Dx = Dt Then 'если високосный прибавим 366 дней D = D + 366 Else D = D + 365 End If Incr Dt Loop Until Dt = Y1 'не учитываем год проверки, выходим If Dy = Y1 Then 'если год проверки високосный Dd = 366 - Dd Else Dd = 365 - Dd End If D = D + Ds D = D + Dd End If Print D 'печатаем количество пройденных дней End
Результат вычислений записывается в переменную D и отправляется в терминал. Думаю по комментариям в коде будет понятно, куда кладутся значения дат. Проверить работу алгоритма можно во встроенном в Bascom-AVR симуляторе. На скриншоте виден результат подсчета и его сравнение с функцией расчета разницы дат, встроенной в Excel. Удачи!
UPD: А вот алгоритм предложенный уважаемым Mrshilov, использующий в качестве опорной даты 2000й год и занимающий всего 1 кб памяти.
Dim Dd As Long , Temp_long As Long , Temp_word As Word , Temp1_word As Word
Dim Month As Byte , Dat As Byte , Year As Byte '------------------------------------------------------------------------------- Dat = 1 Month = 8 Year = 16 Gosub Days_since 'первая дата Dd = Temp_long Dat = 2 Month = 10 Year = 51 Gosub Days_since 'вторая дата Dd = Temp_long - Dd Print Dd 'результат End '------------------------------------------------------------------------------- Days_since: Temp_word = Year + 2000 'дней от 2000 года Temp_long = Temp_word * 367 Temp1_word = Month + 9 Temp1_word = Temp1_word / 12 Temp1_word = Temp_word + Temp1_word Temp1_word = Temp1_word * 7 Temp1_word = Temp1_word / 4 Temp_long = Temp_long - Temp1_word Temp1_word = Month * 275 Temp1_word = Temp1_word / 9 Temp_long = Temp_long + Temp1_word Temp_long = Temp_long + Dat Temp_long = Temp_long - 730530 Return
| |
Просмотров: 13372 | Комментарии: 7 | Рейтинг: 5.0/7 |
Всего комментариев: 7 | ||||||
| ||||||
Проекты [46] |
Как подключить [32] |
Инструменты [3] |
Полезная информация [18] |
Объявления [3] |