Потребовалось мне тут узнавать из Интернета текущее время и дату. Ну, получить длинное число из NTP нетрудно, но потом же надо в дату и время пересчитать! Запустил IDE 1.6.5 и с тоской обнаружил, что там нет службы времени («time.h»). Полез на сайт Atmel в документацию библиотеки AVR LibC и с ещё большей тоской обнаружил, что её нет и там. Те, кто когда-либо работал с NTP, поймут мою тоску – время там узнать несложно, а вот дату без библиотечных функций – гороху накушаешься. Требуется очень аккуратная программа строк на сто – в общем, полдня возни.
Но, чёрт меня дёрнул запустить IDE 1.6.12 (типа, для очистки совести) – а оно там есть!
Таким образом, в поздних версиях IDE (вернее, библиотеки AVR LibC) имеется недокументированная служба времени. С какой версии IDE она появилась, я выяснять не стал, но точно могу сказать, что в 1.6.5 ещё не было, а в 1.6.12 уже есть.
Попробовал применить, а вот фигвам! Считая, что в типе time_t как и положено лежит UNIX-время, т.е. секунды с 01.01.1970, я ввёл поправку на NTP время (секунды с 01.01.1900) и … получил, что сегодня 2047 год.
Полез в исходники AVR LibC – документации-то нету :( Нарыл следующую информацию – в типе time_t они хранят не UNIX-время как все нормальные люди, а секунды с 01.01.2000. Отсюда и моя ошибка в 30 лет. Правда, они определили константы для пересчёта их времени в UNIX и в NTP – и на том спасибо.
На всякий случай проверил, что хранится в поле tm_year структуры struct tm. Здесь у них всё стандартно – год с 1900, как у всех.
Вот скетч – пример использования службы времени. Работа с NTP сюда не включена, а просто вставил константу 3693471153, которую я получил сегодня от NTP сервера. Она соответствует времени 15.01.2017 15:12:33. Смотрите в скетче, как из этого числа можно получить структуру struct tm (а в ней уже есть все – время, дата, день недели и т.п.).
04 | #define GOT_FROM_NTP 3693471153UL // 15.01.2017 15:12:33 |
05 | #define MOSCOW_TIME (3 * ONE_HOUR) |
09 | unsigned long tt = GOT_FROM_NTP - NTP_OFFSET; |
10 | set_zone(MOSCOW_TIME); |
11 | const struct tm * timeinfo = localtime(&tt); |
12 | Serial .print( "struct tm year: " ); |
13 | Serial .println(timeinfo->tm_year); |
15 | strftime(szTime, sizeof (szTime), "%A, %B %d, %Y. %T" , timeinfo); |
16 | Serial .println(szTime); |
21 | /////////////////////////////////////// |
22 | //// RESULT (IDE 1.6.12) ////////////// |
В порядке справки, приведу также и структуру struct tm, для тех, кто её не знает.
Виноват, в строке 9 более грамотно использовать тип time_t, а не unsigned long, хотя в данной реализации это одно и то же. У меня этот тип случайно остался от NTP-шной программы - забыл поменять.
А в остальном нормальная библиотека? Что там есть, чего нет? Локализации-то поди точно нет.
А в остальном нормальная библиотека? Что там есть, чего нет? Локализации-то поди точно нет.
Вот полный заголовочный файл time.h из avr libc 1.8.1
001
/*
002
* (C)2012 Michael Duane Rice All rights reserved.
003
*
004
* Redistribution and use in source and binary forms, with or without
005
* modification, are permitted provided that the following conditions are
006
* met:
007
*
008
* Redistributions of source code must retain the above copyright notice, this
009
* list of conditions and the following disclaimer. Redistributions in binary
010
* form must reproduce the above copyright notice, this list of conditions
011
* and the following disclaimer in the documentation and/or other materials
012
* provided with the distribution. Neither the name of the copyright holders
013
* nor the names of contributors may be used to endorse or promote products
014
* derived from this software without specific prior written permission.
015
*
016
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
017
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
018
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
019
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
020
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
021
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
022
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
023
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
024
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
025
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
026
* POSSIBILITY OF SUCH DAMAGE.
027
*/
028
029
/* $Id: time.h 2427 2014-05-01 14:06:03Z amylaar $ */
030
031
/** \file */
032
033
/** \defgroup avr_time <time.h>: Time
034
\code #include <time.h> \endcode
035
<h3>Introduction to the Time functions</h3>
036
This file declares the time functions implemented in \c avr-libc.
037
038
The implementation aspires to conform with ISO/IEC 9899 (C90). However, due to limitations of the
039
target processor and the nature of its development environment, a practical implementation must
040
of necessity deviate from the standard.
041
042
043
044
Section 7.23.2.1 clock()
045
The type clock_t, the macro CLOCKS_PER_SEC, and the function clock() are not implemented. We
046
consider these items belong to operating system code, or to application code when no operating
047
system is present.
048
049
Section 7.23.2.3 mktime()
050
The standard specifies that mktime() should return (time_t) -1, if the time cannot be represented.
051
This implementation always returns a 'best effort' representation.
052
053
Section 7.23.2.4 time()
054
The standard specifies that time() should return (time_t) -1, if the time is not available.
055
Since the application must initialize the time system, this functionality is not implemented.
056
057
Section 7.23.2.2, difftime()
058
Due to the lack of a 64 bit double, the function difftime() returns a long integer. In most cases
059
this change will be invisible to the user, handled automatically by the compiler.
060
061
Section 7.23.1.4 struct tm
062
Per the standard, struct tm->tm_isdst is greater than zero when Daylight Saving time is in effect.
063
This implementation further specifies that, when positive, the value of tm_isdst represents
064
the amount time is advanced during Daylight Saving time.
065
066
Section 7.23.3.5 strftime()
067
Only the 'C' locale is supported, therefore the modifiers 'E' and 'O' are ignored.
068
The 'Z' conversion is also ignored, due to the lack of time zone name.
069
070
In addition to the above departures from the standard, there are some behaviors which are different
071
from what is often expected, though allowed under the standard.
072
073
There is no 'platform standard' method to obtain the current time, time zone, or
074
daylight savings 'rules' in the AVR environment. Therefore the application must initialize
075
the time system with this information. The functions set_zone(), set_dst(), and
076
set_system_time() are provided for initialization. Once initialized, system time is maintained by
077
calling the function system_tick() at one second intervals.
078
079
Though not specified in the standard, it is often expected that time_t is a signed integer
080
representing an offset in seconds from Midnight Jan 1 1970... i.e. 'Unix time'. This implementation
081
uses an unsigned 32 bit integer offset from Midnight Jan 1 2000. The use of this 'epoch' helps to
082
simplify the conversion functions, while the 32 bit value allows time to be properly represented
083
until Tue Feb 7 06:28:15 2136 UTC. The macros UNIX_OFFSET and NTP_OFFSET are defined to assist in
084
converting to and from Unix and NTP time stamps.
085
086
Unlike desktop counterparts, it is impractical to implement or maintain the 'zoneinfo' database.
087
Therefore no attempt is made to account for time zone, daylight saving, or leap seconds in past dates.
088
All calculations are made according to the currently configured time zone and daylight saving 'rule'.
089
090
In addition to C standard functions, re-entrant versions of ctime(), asctime(), gmtime() and
091
localtime() are provided which, in addition to being re-entrant, have the property of claiming
092
less permanent storage in RAM. An additional time conversion, isotime() and its re-entrant version,
093
uses far less storage than either ctime() or asctime().
094
095
Along with the usual smattering of utility functions, such as is_leap_year(), this library includes
096
a set of functions related the sun and moon, as well as sidereal time functions.
097
*/
098
099
#ifndef TIME_H
100
#define TIME_H
101
102
#ifdef __cplusplus
103
extern
"C"
{
104
#endif
105
106
#include <inttypes.h>
107
#include <stdlib.h>
108
109
/** \ingroup avr_time */
110
/* @{ */
111
112
/**
113
time_t represents seconds elapsed from Midnight, Jan 1 2000 UTC (the Y2K 'epoch').
114
Its range allows this implementation to represent time up to Tue Feb 7 06:28:15 2136 UTC.
115
*/
116
typedef uint32_t time_t;
117
118
/**
119
The time function returns the systems current time stamp.
120
If timer is not a null pointer, the return value is also assigned to the object it points to.
121
*/
122
time_t time(time_t *timer);
123
124
/**
125
The difftime function returns the difference between two binary time stamps,
126
time1 - time0.
127
*/
128
int32_t difftime(time_t time1, time_t time0);
129
130
131
/**
132
The tm structure contains a representation of time 'broken down' into components of the
133
Gregorian calendar.
134
135
The normal ranges of the elements are..
136
137
\code
138
tm_sec seconds after the minute - [ 0 to 59 ]
139
tm_min minutes after the hour - [ 0 to 59 ]
140
tm_hour hours since midnight - [ 0 to 23 ]
141
tm_mday day of the month - [ 1 to 31 ]
142
tm_wday days since Sunday - [ 0 to 6 ]
143
tm_mon months since January - [ 0 to 11 ]
144
tm_year years since 1900
145
tm_yday days since January 1 - [ 0 to 365 ]
146
tm_isdst Daylight Saving Time flag *
147
148
\endcode
149
150
*The value of tm_isdst is zero if Daylight Saving Time is not in effect, and is negative if
151
the information is not available.
152
153
When Daylight Saving Time is in effect, the value represents the number of
154
seconds the clock is advanced.
155
156
See the set_dst() function for more information about Daylight Saving.
157
158
*/
159
struct
tm {
160
int8_t tm_sec;
161
int8_t tm_min;
162
int8_t tm_hour;
163
int8_t tm_mday;
164
int8_t tm_wday;
165
int8_t tm_mon;
166
int16_t tm_year;
167
int16_t tm_yday;
168
int16_t tm_isdst;
169
};
170
171
172
/* We have to provide clock_t / CLOCKS_PER_SEC so that libstdc++-v3 can
173
be built. We define CLOCKS_PER_SEC via a symbol _CLOCKS_PER_SEC_
174
so that the user can provide the value on the link line, which should
175
result in little or no run-time overhead compared with a constant. */
176
typedef unsigned
long
clock_t;
177
extern
char
*_CLOCKS_PER_SEC_;
178
#define CLOCKS_PER_SEC ((clock_t) _CLOCKS_PER_SEC_)
179
extern
clock_t clock(
void
);
180
181
/**
182
This function 'compiles' the elements of a broken-down time structure, returning a binary time stamp.
183
The elements of timeptr are interpreted as representing Local Time.
184
185
The original values of the tm_wday and tm_yday elements of the structure are ignored,
186
and the original values of the other elements are not restricted to the ranges stated for struct tm.
187
188
On successful completion, the values of all elements of timeptr are set to the appropriate range.
189
*/
190
time_t mktime(
struct
tm * timeptr);
191
192
/**
193
This function 'compiles' the elements of a broken-down time structure, returning a binary time stamp.
194
The elements of timeptr are interpreted as representing UTC.
195
196
The original values of the tm_wday and tm_yday elements of the structure are ignored,
197
and the original values of the other elements are not restricted to the ranges stated for struct tm.
198
199
Unlike mktime(), this function DOES NOT modify the elements of timeptr.
200
*/
201
time_t mk_gmtime(
const
struct
tm * timeptr);
202
203
/**
204
The gmtime function converts the time stamp pointed to by timer into broken-down time,
205
expressed as UTC.
206
*/
207
struct
tm *gmtime(
const
time_t * timer);
208
209
/**
210
Re entrant version of gmtime().
211
*/
212
void
gmtime_r(
const
time_t * timer,
struct
tm * timeptr);
213
214
/**
215
The localtime function converts the time stamp pointed to by timer into broken-down time,
216
expressed as Local time.
217
*/
218
struct
tm *localtime(
const
time_t * timer);
219
220
/**
221
Re entrant version of localtime().
222
*/
223
void
localtime_r(
const
time_t * timer,
struct
tm * timeptr);
224
225
/**
226
The asctime function converts the broken-down time of timeptr, into an ascii string in the form
227
228
Sun Mar 23 01:03:52 2013
229
*/
230
char
*asctime(
const
struct
tm * timeptr);
231
232
/**
233
Re entrant version of asctime().
234
*/
235
void
asctime_r(
const
struct
tm * timeptr,
char
*buf);
236
237
/**
238
The ctime function is equivalent to asctime(localtime(timer))
239
*/
240
char
*ctime(
const
time_t * timer);
241
242
/**
243
Re entrant version of ctime().
244
*/
245
void
ctime_r(
const
time_t * timer,
char
*buf);
246
247
/**
248
The isotime function constructs an ascii string in the form
249
\code2013-03-23 01:03:52\endcode
250
*/
251
char
*isotime(
const
struct
tm * tmptr);
252
253
/**
254
Re entrant version of isotime()
255
*/
256
void
isotime_r(
const
struct
tm *,
char
*);
257
258
/**
259
A complete description of strftime() is beyond the pale of this document.
260
Refer to ISO/IEC document 9899 for details.
261
262
All conversions are made using the 'C Locale', ignoring the E or O modifiers. Due to the lack of
263
a time zone 'name', the 'Z' conversion is also ignored.
264
*/
265
size_t strftime(
char
*s, size_t maxsize,
const
char
*format,
const
struct
tm * timeptr);
266
267
/**
268
Specify the Daylight Saving function.
269
270
The Daylight Saving function should examine its parameters to determine whether
271
Daylight Saving is in effect, and return a value appropriate for tm_isdst.
272
273
Working examples for the USA and the EU are available..
274
275
\code #include <util/eu_dst.h>\endcode
276
for the European Union, and
277
\code #include <util/usa_dst.h>\endcode
278
for the United States
279
280
If a Daylight Saving function is not specified, the system will ignore Daylight Saving.
281
*/
282
void
set_dst(
int
(*) (
const
time_t *, int32_t *));
283
284
/**
285
Set the 'time zone'. The parameter is given in seconds East of the Prime Meridian.
286
Example for New York City:
287
\code set_zone(-5 * ONE_HOUR);\endcode
288
289
If the time zone is not set, the time system will operate in UTC only.
290
*/
291
void
set_zone(int32_t);
292
293
/**
294
Initialize the system time. Examples are...
295
296
From a Clock / Calendar type RTC:
297
\code
298
struct tm rtc_time;
299
300
read_rtc(&rtc_time);
301
rtc_time.tm_isdst = 0;
302
set_system_time( mktime(&rtc_time) );
303
\endcode
304
305
From a Network Time Protocol time stamp:
306
\code
307
set_system_time(ntp_timestamp - NTP_OFFSET);
308
\endcode
309
310
From a UNIX time stamp:
311
\code
312
set_system_time(unix_timestamp - UNIX_OFFSET);
313
\endcode
314
315
*/
316
void
set_system_time(time_t timestamp);
317
318
/**
319
Maintain the system time by calling this function at a rate of 1 Hertz.
320
321
It is anticipated that this function will typically be called from within an
322
Interrupt Service Routine, (though that is not required). It therefore includes code which
323
makes it simple to use from within a 'Naked' ISR, avoiding the cost of saving and restoring
324
all the cpu registers.
325
326
Such an ISR may resemble the following example...
327
\code
328
ISR(RTC_OVF_vect, ISR_NAKED)
329
{
330
system_tick();
331
reti();
332
}
333
\endcode
334
*/
335
void
system_tick(
void
);
336
337
/**
338
Enumerated labels for the days of the week.
339
*/
340
enum
_WEEK_DAYS_ {
341
SUNDAY,
342
MONDAY,
343
TUESDAY,
344
WEDNESDAY,
345
THURSDAY,
346
FRIDAY,
347
SATURDAY
348
};
349
350
/**
351
Enumerated labels for the months.
352
*/
353
enum
_MONTHS_ {
354
JANUARY,
355
FEBRUARY,
356
MARCH,
357
APRIL,
358
MAY,
359
JUNE,
360
JULY,
361
AUGUST,
362
SEPTEMBER,
363
OCTOBER,
364
NOVEMBER,
365
DECEMBER
366
};
367
368
/**
369
Return 1 if year is a leap year, zero if it is not.
370
*/
371
uint8_t is_leap_year(int16_t year);
372
373
/**
374
Return the length of month, given the year and month, where month is in the range 1 to 12.
375
*/
376
uint8_t month_length(int16_t year, uint8_t month);
377
378
/**
379
Return the calendar week of year, where week 1 is considered to begin on the
380
day of week specified by 'start'. The returned value may range from zero to 52.
381
*/
382
uint8_t week_of_year(
const
struct
tm * timeptr, uint8_t start);
383
384
/**
385
Return the calendar week of month, where the first week is considered to begin on the
386
day of week specified by 'start'. The returned value may range from zero to 5.
387
*/
388
uint8_t week_of_month(
const
struct
tm * timeptr, uint8_t start);
389
390
/**
391
Structure which represents a date as a year, week number of that year, and day of week.
392
See <a href="http://en.wikipedia.org/wiki/ISO_week_date" title="http://en.wikipedia.org/wiki/ISO_week_date" rel="nofollow">http://en.wikipedia.org/wiki/ISO_week_date</a> for more information.
393
*/
394
struct
week_date{
395
int
year;
396
int
week;
397
int
day;
398
};
399
400
/**
401
Return a week_date structure with the ISO_8601 week based date corresponding to the given
402
year and day of year. See <a href="http://en.wikipedia.org/wiki/ISO_week_date" title="http://en.wikipedia.org/wiki/ISO_week_date" rel="nofollow">http://en.wikipedia.org/wiki/ISO_week_date</a> for more
403
information.
404
*/
405
struct
week_date * iso_week_date(
int
year,
int
yday);
406
407
/**
408
Re-entrant version of iso-week_date.
409
*/
410
void
iso_week_date_r(
int
year,
int
yday,
struct
week_date *);
411
412
/**
413
Convert a Y2K time stamp into a FAT file system time stamp.
414
*/
415
uint32_t fatfs_time(
const
struct
tm * timeptr);
416
417
/** One hour, expressed in seconds */
418
#define ONE_HOUR 3600
419
420
/** Angular degree, expressed in arc seconds */
421
#define ONE_DEGREE 3600
422
423
/** One day, expressed in seconds */
424
#define ONE_DAY 86400
425
426
/** Difference between the Y2K and the UNIX epochs, in seconds. To convert a Y2K
427
timestamp to UNIX...
428
\code
429
long unix;
430
time_t y2k;
431
432
y2k = time(NULL);
433
unix = y2k + UNIX_OFFSET;
434
\endcode
435
*/
436
#define UNIX_OFFSET 946684800
437
438
/** Difference between the Y2K and the NTP epochs, in seconds. To convert a Y2K
439
timestamp to NTP...
440
\code
441
unsigned long ntp;
442
time_t y2k;
443
444
y2k = time(NULL);
445
ntp = y2k + NTP_OFFSET;
446
\endcode
447
*/
448
#define NTP_OFFSET 3155673600
449
450
/*
451
* ===================================================================
452
* Ephemera
453
*/
454
455
/**
456
Set the geographic coordinates of the 'observer', for use with several of the
457
following functions. Parameters are passed as seconds of North Latitude, and seconds
458
of East Longitude.
459
460
For New York City...
461
\code set_position( 40.7142 * ONE_DEGREE, -74.0064 * ONE_DEGREE); \endcode
462
*/
463
void
set_position(int32_t latitude, int32_t longitude);
464
465
/**
466
Computes the difference between apparent solar time and mean solar time.
467
The returned value is in seconds.
468
*/
469
int16_t equation_of_time(
const
time_t * timer);
470
471
/**
472
Computes the amount of time the sun is above the horizon, at the location of the observer.
473
474
NOTE: At observer locations inside a polar circle, this value can be zero during the winter,
475
and can exceed ONE_DAY during the summer.
476
477
The returned value is in seconds.
478
*/
479
int32_t daylight_seconds(
const
time_t * timer);
480
481
/**
482
Computes the time of solar noon, at the location of the observer.
483
*/
484
time_t solar_noon(
const
time_t * timer);
485
486
/**
487
Return the time of sunrise, at the location of the observer. See the note about daylight_seconds().
488
*/
489
time_t sun_rise(
const
time_t * timer);
490
491
/**
492
Return the time of sunset, at the location of the observer. See the note about daylight_seconds().
493
*/
494
time_t sun_set(
const
time_t * timer);
495
496
/** Returns the declination of the sun in radians. */
497
double
solar_declination(
const
time_t * timer);
498
499
/**
500
Returns an approximation to the phase of the moon.
501
The sign of the returned value indicates a waning or waxing phase.
502
The magnitude of the returned value indicates the percentage illumination.
503
*/
504
int8_t moon_phase(
const
time_t * timer);
505
506
/**
507
Returns Greenwich Mean Sidereal Time, as seconds into the sidereal day.
508
The returned value will range from 0 through 86399 seconds.
509
*/
510
unsigned
long
gm_sidereal(
const
time_t * timer);
511
512
/**
513
Returns Local Mean Sidereal Time, as seconds into the sidereal day.
514
The returned value will range from 0 through 86399 seconds.
515
*/
516
unsigned
long
lm_sidereal(
const
time_t * timer);
517
518
/* @} */
519
#ifdef __cplusplus
520
}
521
#endif
522
523
#endif /* TIME_H */
Если что, то на Pjrc.com есть рабочая библиотека "time" с прмерами..
Ну, Dimax, здесь всё-таки полная С-шная стандартная библиотека к которой многие уж десятилетия как привыкли.
Вот, недавно была тема где автор собирался массив времени восхода на весь год иметь, а тут - ввёл свои координаты и получай хоть восход, хоть закат ...
Оно как-то когда это устоявшийся стандарт как-то приятниее.
кто как понимает этот кусок комментариев в time.h ? (*ТС, можешь не выскакивать с воплями о платности своих услуг)
01
/**
02
Maintain the system time by calling this function at a rate of 1 Hertz.
03
04
It is anticipated that this function will typically be called from within an
05
Interrupt Service Routine, (though that is not required). It therefore includes code which
06
makes it simple to use from within a 'Naked' ISR, avoiding the cost of saving and restoring
07
all the cpu registers.
08
09
Such an ISR may resemble the following example...
10
\code
11
ISR(RTC_OVF_vect, ISR_NAKED)
12
{
13
system_tick();
14
reti();
15
}
16
\endcode
17
*/
так понимаю, что нужно каждую секунду запускать system_tick(); и reti();
ок.
запускается system_tick(); - и, чего?
1
void
system_tick(
void
);
и, не запускается reti(); - нет о нём ничего в коде.
*по идее, должно быть как-то так
1
void
system_tick(
void
) {rtc_time++};
*по идее, должно быть как-то так
1
void
system_tick(
void
) {rtc_time++};
Насчет reti() не знаю, а вот system_tick(), как я понял, наращивает volatile time_t __system_time. Для чего? Возможно для портированного кода, который захочет получить текущее время через стандартную time(), которая и возвращает эту глобальную переменную.
а вот system_tick(), как я понял, наращивает volatile time_t __system_time.
а, как ты это понял? - где находится код, который что-то наращивает?
и, где смотреть __system_time ?
avr-libc-2.0.0/libc/time/
time.c
01
extern
volatile time_t __system_time;
02
03
time_t
04
time(time_t * timer)
05
{
06
time_t ret;
07
08
asm volatile(
09
"in __tmp_reg__, __SREG__"
"\n\t"
10
"cli"
"\n\t"
11
::
12
);
13
ret = __system_time;
14
asm volatile(
15
"out __SREG__, __tmp_reg__"
"\n\t"
16
::
17
);
18
if
(timer)
19
*timer = ret;
20
return
ret;
21
}
system_tick.S:
01
/* $Id: system_tick.S 2348 2013-04-16 23:42:05Z swfltek $ */
02
03
/*
04
Impoved system_tick Credit to Wouter van Gulik.
05
*/
06
07
#include <avr/common.h>
08
09
.global system_tick
10
.type system_tick, @function
11
system_tick:
12
push r24
13
in
r24,_SFR_IO_ADDR(SREG)
14
push r24
15
cli
16
lds r24,__system_time+0
17
subi r24, (-1)
18
sts __system_time+0,r24
19
lds r24,__system_time+1
20
sbci r24, (-1)
21
sts __system_time+1,r24
22
lds r24,__system_time+2
23
sbci r24, (-1)
24
sts __system_time+2,r24
25
lds r24,__system_time+3
26
sbci r24, (-1)
27
sts __system_time+3,r24
28
pop r24
29
out
_SFR_IO_ADDR(SREG),r24
30
pop r24
31
ret
32
.size system_tick, .-system_tick
ок. спасибо.
Я своей функцией пользуюсь для пересчёта из time_t, она входит в состав логгера для telnet сервера (GetTimeAsSystemTime).
Я своей функцией пользуюсь для пересчёта из time_t, она входит в состав логгера для telnet сервера (GetTimeAsSystemTime).
Евгений, а как проверить насколько правильно сия библиотека рассчитывает локальное время? Могу к примеру сказать для любого города точное локальное время. Сравним?
Очень точно рассчитывает. Только UTC offset задайте правильно ;)
Есть специальный онлайн сервис, где можно конвертировать время: Epoch & Unix Timestamp Conversion Tools
На самом деле нет никаких "нестандартных и недокументированных служб". Есть давно стандартизированный набор unix'овых функций для преобразования данных о времени в разные формы (в т.ч. строковый). Поскольку математика работы со временем одна, то нестандартной она быть не может. В моём случае я описал по-русски почти каждое действие. Существует несколько программных реализаций подобных алгоритмов.
Также нужно иметь в виду, что начало отсчёта называется эпохой. Дату 1970 называют эпохой unix. Вы можете выбрать любую удобную для вас дату, имея в виду, что интервал времени в 32-битном числе получается не такой уж и большой. Для эпохи unix в 2030-х годах наступит переполнение для устройств, которые используют 32-битные счётчики. Если же эту дату отодвинуть чуть на попозже, то и время аппокалипсиса тоже отодвинется. Поэтому некоторые товарищи берут за начала отсчёта другие даты. Об этом можно почитать в википедии.
Очень точно рассчитывает. Только UTC offset задайте правильно ;)
А код не сможете привести, ну я ни разу не программист, сам точно не напишу
В качестве примечания: эти некоторые товарищи точкой отсчета в avr-libc версии <time.h> взяли 00:00:00 01/01/2000, базируясь тем самым на "Y2K epoch", что может доставить определенные проблемы при взаимодействии со внешними системами. Нужно своевременно корректировать timestamp на UNIX_OFFSET. Видимо это и есть нестандартность данной реализации, как и указанно в первом посте.
нашлась reti() в interrupt.h
1
# define reti() __asm__ __volatile__ ("reti" ::)
А код не сможете привести, ну я ни разу не программист, сам точно не напишу
Вот он, в первом посте:
5
#define MOSCOW_TIME (3 * ONE_HOUR)
06
10
set_zone(MOSCOW_TIME);
11
const
struct
tm * timeinfo = localtime(&tt);
Учтите, что действие глобальной переменной __utc_offset, устанавливаемой при помощи set_zone() распространяется только на функции localtime_r(), localtime(), mktime() и частично на strftime(). В отношении последней есть примечание: "All conversions are made using the 'C Locale', ignoring the E or O modifiers. Due to the lack of a time zone 'name', the 'Z' conversion is also ignored."
нашлась reti() в interrupt.h
1
# define reti() __asm__ __volatile__ ("reti" ::)
....гы!
-Рубашка нашлась, Петька! Она под майкой была! ©
Учтите, что действие глобальной переменной __utc_offset, устанавливаемой при помощи set_zone() распространяется только на функции localtime_r(), localtime(), mktime() и частично на strftime(). В отношении последней есть примечание: "All conversions are made using the 'C Locale', ignoring the E or O modifiers. Due to the lack of a time zone 'name', the 'Z' conversion is also ignored."
А координаты где вводить?
Координаты мерьканских секретных объектов?
http://www.nongnu.org/avr-libc/user-manual/group__avr__time.html - set_position().
Только на таймзону они никак не влияют, если что.
А координаты где вводить?
Координаты не влияют на локальное время. Они нужны для определения времени восхода, заката и т.п.
ТС, можешь не выскакивать с воплями о платности своих услуг
Могу и не выскакивать. Молодец, что запомнил!
насколько правильно сия библиотека рассчитывает локальное время?
Ни на сколько вообще. Вы сами задаёте UTC и сами же задаёте часовой пояс - её дело тупо сложить.
Могу и не выскакивать. Молодец, что запомнил!
таки, не выдержал - выскочил.
кто в курсе зачем в разных примерах по разному объявляется структура tm ?
1
time_t s = time(NULL);
2
const
struct
tm * seconds = localtime(&s);
// 1-й вариант
3
struct
tm * seconds = localtime(&s);
// 2-й вариант
4
tm * seconds = localtime(&s);
// 3-й вариант
Координаты мерьканских секретных объектов?
http://www.nongnu.org/avr-libc/user-manual/group__avr__time.html - set_position().
Только на таймзону они никак не влияют, если что.
Таки и не должны, они влияют на рассчет слежения трекера за спутниками к примеру, но кеплеровские данные всё равно придётся обновлять, хотя бы раз в месяц
Пример определения времени восхода солнца для двух разных городов.
01
#include <time.h>
02
//
03
// Москва 55°45'07" с.ш., 37°36'59" в.д.
04
#define MOSCOW \
05
static_cast<int32_t>(ONE_DEGREE * 55.75194), \
06
static_cast<int32_t>(ONE_DEGREE * 37.61639)
07
//
08
// Урюпинск 50°48′00″ с. ш. 42°01′00″ в.д.
09
#define URUPINSK \
10
static_cast<int32_t>(ONE_DEGREE * 50.8), \
11
static_cast<int32_t>(ONE_DEGREE * 42.0167)
12
//
13
// Временная зона (UTC + 3)
14
static
constexpr int32_t timeZoneMoscow = static_cast<int32_t>(3) * ONE_HOUR;
15
16
//
17
// Восход для текущей локации (врзвращает время в тексте)
18
static
void
getSunRise(
const
time_t today,
char
* buffer,
const
size_t bufSize) {
19
time_t sr = sun_rise(& today);
20
struct
tm * sr_time = localtime(& sr);
21
strftime(buffer, bufSize,
"\t%X"
, sr_time);
22
}
23
24
void
setup
(
void
) {
25
Serial
.begin(115200);
26
//
27
// Январь 2020 года
28
struct
tm theDate = {0, 0, 12, 1, 0, 0, 120, 0, 0};
29
//
30
// Время московское
31
set_zone(timeZoneMoscow);
32
//
33
// Заголовок
34
Serial
.println(
"SUNRISE for both Moscow and Urupinsк for January 2020\r\n\tDate\t\t\tMoscow\t\tUrupinsk"
);
35
//
36
// Цикл по всем дня месяца (января)
37
for
(
int
dayOfMonth = 1; (theDate.tm_mday = dayOfMonth) < 32; dayOfMonth++) {
38
//
39
// Компиляция даты
40
time_t today = mktime(& theDate);
41
//
42
// Печать даты
43
char
buffer[64];
44
strftime(buffer,
sizeof
(buffer),
"%A, %B %d, %Y"
, & theDate);
45
Serial
.print(buffer);
46
//
47
// Печать времени восхода для Москвы
48
set_position(MOSCOW);
49
getSunRise(today, buffer,
sizeof
(buffer));
50
Serial
.print(buffer);
51
//
52
// Печать времени восхода для Урюпинска
53
set_position(URUPINSK);
54
getSunRise(today, buffer,
sizeof
(buffer));
55
Serial
.println(buffer);
56
}
57
}
58
59
void
loop
(
void
) {}
Результат работы
SUNRISE
for
both Moscow and Urupinsк
for
January 2020
Date Moscow Urupinsk
Wednesday, January 01, 2020 09:05:26 08:18:36
Thursday, January 02, 2020 09:05:10 08:18:31
Friday, January 03, 2020 09:04:51 08:18:22
Saturday, January 04, 2020 09:04:28 08:18:11
Sunday, January 05, 2020 09:04:01 08:17:56
Monday, January 06, 2020 09:03:30 08:17:39
Tuesday, January 07, 2020 09:02:55 08:17:18
Wednesday, January 08, 2020 09:02:16 08:16:54
Thursday, January 09, 2020 09:01:34 08:16:27
Friday, January 10, 2020 09:00:48 08:15:57
Saturday, January 11, 2020 08:59:58 08:15:24
Sunday, January 12, 2020 08:59:04 08:14:47
Monday, January 13, 2020 08:58:08 08:14:08
Tuesday, January 14, 2020 08:57:08 08:13:27
Wednesday, January 15, 2020 08:56:05 08:12:43
Thursday, January 16, 2020 08:54:57 08:11:55
Friday, January 17, 2020 08:53:47 08:11:05
Saturday, January 18, 2020 08:52:34 08:10:11
Sunday, January 19, 2020 08:51:17 08:09:15
Monday, January 20, 2020 08:49:57 08:08:17
Tuesday, January 21, 2020 08:48:34 08:07:15
Wednesday, January 22, 2020 08:47:09 08:06:12
Thursday, January 23, 2020 08:45:41 08:05:06
Friday, January 24, 2020 08:44:09 08:03:57
Saturday, January 25, 2020 08:42:35 08:02:45
Sunday, January 26, 2020 08:40:59 08:01:32
Monday, January 27, 2020 08:39:19 08:00:16
Tuesday, January 28, 2020 08:37:37 07:58:57
Wednesday, January 29, 2020 08:35:53 07:57:37
Thursday, January 30, 2020 08:34:07 07:56:14
Friday, January 31, 2020 08:32:17 07:54:48
Замечание: здесь не учитывается высота данного места над уровнем моря, потому время может на несколько минут отличаться от фактического.
Во, блин! Совсем уж собрался писать про ещё одну нестандартность, но всё не так просто.
Была у меня в древнем, как фортран, проекте под Visual Studio (VS) функция для вычисления дня недели
01
/// <summary>
02
/// Возвращает день недели
03
/// </summary>
04
/// <param name="day">день месяца (1-31)</param>
05
/// <param name="month">месяц (1-12)</param>
06
/// <param name="year">год полностью</param>
07
/// <returns>день недели 0-воскресенье, 1-понедельник, ..., 6-суббота, или -1 если ошибка</returns>
08
//
09
uint8_t getWeekDay(
const
uint8_t day,
const
uint8_t month,
const
uint16_t year) {
10
tm theTm = { 0, 0, 0, day, month - 1, year - 1900 };
11
return
(mktime(& theTm) < 0) ? -1 : theTm.tm_wday;
12
}
и ведь, ЧСХ, знаю, что говнокод, всегда говорил и студентам, и детям, и внукам, что так делать не стоит, но вот такая она у меня - эта функция. :-( Служила она мне верой и правдой во многих программах.
Решил перетащить в атмеловскую студию (AS) (всё, что сказано ниже, верно и для Arduino IDE). Что-то пошло не так. Ну, эта функция много лет верой и правдой, потому, её подозреваем в самую последнюю очередь. Час траха, чтобы выяснить, что таки она, сука, неправильно считает. Как же так?!? Ещё немного траха и тут выясняется, что структуры tm в VS и в AS - разные!
Т.е. у майкрософта день недели стоит после месяца и года, а у Атмела - перед - твающ...!
Ну, чё, решил разобраться, кто не прав: Atmel или Microsoft.
Открываем стандарт языка Си (ISO/IEC 9899:2018, § 7.27.1 Library, page. 285) и читаем
Вывод: и Майкрософт и Атмел, оба правы. Неправ ЕвгенийП, в том, что использует неназначенную инициализацию структуры!
В порядке придирки отмечу, что у Атмела неверно указан диапазон секунд - 0-59, а должно быть 0-60.
Но самый шок был. когда я полез в казалось бы абсолютно кошерный источник "правильного Си" - https://github.com/torvalds/linux/blob/master/include/linux/time.h и обнаружил, что там-то эта структура стандарту не соответствует - отсутствует поле tm_isdst. Вот так, ни хрена себе!
Надо Торвальду подсказать )))
В порядке придирки отмечу, что у Атмела неверно указан диапазон секунд - 0-59, а должно быть 0-60.
Это очень прикольно. Интересно , почему секунд может быть 60, а минут не может быть ?
Ну, дык, бывает "високосная секунда", а "високосной минуты" не бывает - обидели!
Вот оно че...