Hallo, ich suche einen schlanken C-Code für einen Mikrocontroller, mit dem ich aus der Unix-zeit (Zeit in Sekunden seit dem 1.1.1970) das aktuelle Datum und die aktuelle Uhrzeit berechnen kann.
Du kannst ja mal hier anfangen: http://www.raspberryginger.com/jbailey/minix/html/gmtime_8c-source.html Und das ganze µC-gerecht umcoden. Die #defines findest Du, wenn Du oben auf <time.h> klickst.
So (uint32_t sec ist die Sekunden seit 1.Januar FIRSTYEAR, FIRSTDAY selbiger Wochentag):
1 | #define FIRSTYEAR 1970
|
2 | #define FIRSTDAY 4 // 0 = Sunday
|
3 | |
4 | struct time { |
5 | uint8_t second; |
6 | uint8_t minute; |
7 | uint8_t hour; |
8 | uint8_t day; |
9 | uint8_t month; |
10 | uint16_t year; |
11 | uint8_t wday; |
12 | };
|
13 | |
14 | /* Definitions */
|
15 | const uint8_t DayOfMonth[] PROGMEM = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
16 | |
17 | #define getMonthLen(a) pgm_read_byte(&(DayOfMonth[(a)]))
|
18 | |
19 | void gettime( uint32_t sec, struct time *t ) |
20 | {
|
21 | uint16_t day; |
22 | uint8_t year; |
23 | uint16_t dayofyear; |
24 | uint8_t leap400; |
25 | uint8_t month; |
26 | |
27 | t->second = sec % 60; |
28 | sec /= 60; |
29 | t->minute = sec % 60; |
30 | sec /= 60; |
31 | t->hour = sec % 24; |
32 | day = sec / 24; |
33 | t->wday = (day + FIRSTDAY) % 7; // weekday |
34 | |
35 | year = FIRSTYEAR % 100; // 0..99 |
36 | leap400 = 4 - ((FIRSTYEAR - 1) / 100 & 3); // 4, 3, 2, 1 |
37 | |
38 | for(;;) |
39 | {
|
40 | dayofyear = 365; |
41 | if( (year & 3) == 0 ) |
42 | {
|
43 | dayofyear = 366; // leap year |
44 | if( year == 0 || year == 100 || year == 200 ) // 100 year exception |
45 | if( --leap400 ) // 400 year exception |
46 | dayofyear = 365; |
47 | }
|
48 | if( day < dayofyear ) |
49 | break; |
50 | day -= dayofyear; |
51 | year++; // 00..136 / 99..235 |
52 | }
|
53 | t->year = year + (int)(FIRSTYEAR / 100) * 100; // + century |
54 | |
55 | if( dayofyear & 1 && day > 58 ) // no leap year and after 28.2. |
56 | day++; // skip 29.2. |
57 | |
58 | for( month = 1; day >= getMonthLen(month-1); month++ ) |
59 | day -= getMonthLen(month-1); |
60 | |
61 | t->month = month; // 1..12 |
62 | t->day = day + 1; // 1..31 |
63 | }
|
Bernhard M. schrieb: > #define getMonthLen(a) pgm_read_byte(&(DayOfMonth[(a)])) Also wenn schon paranoid, dann bitte konsequent: ;-) #define getMonthLen(a) (pgm_read_byte(&(DayOfMonth[(a)])))
A. K. schrieb: > Bernhard M. schrieb: > >> #define getMonthLen(a) pgm_read_byte(&(DayOfMonth[(a)])) > > Also wenn schon paranoid, dann bitte konsequent: ;-) > #define getMonthLen(a) (pgm_read_byte(&(DayOfMonth[(a)]))) da haste recht ;-)
Erst mal danke für den Code, beim Compilieren mit dem MSPGCC werden aber folgende Fehlermeldungen ausgespuckt (wgen der Zeile 79 bei der Übernahme in meinen Code) : [Zeile 79] const uint8_t DayOfMonth[] PROGMEM = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; [Zeile 80] #define getMonthLen(a) (pgm_read_byte(&(DayOfMonth[(a)]))) mod_time01.c:79: syntax error before "PROGMEM" mod_time01.c:79: warning: excess elements in scalar initializer mod_time01.c:79: warning: (near initialization for `PROGMEM') mod_time01.c:79: warning: excess elements in scalar initializer mod_time01.c:79: warning: (near initialization for `PROGMEM') mod_time01.c:79: warning: excess elements in scalar initializer mod_time01.c:79: warning: (near initialization for `PROGMEM') mod_time01.c:79: warning: excess elements in scalar initializer mod_time01.c:79: warning: (near initialization for `PROGMEM') mod_time01.c:79: warning: excess elements in scalar initializer mod_time01.c:79: warning: (near initialization for `PROGMEM') mod_time01.c:79: warning: excess elements in scalar initializer mod_time01.c:79: warning: (near initialization for `PROGMEM') mod_time01.c:79: warning: excess elements in scalar initializer mod_time01.c:79: warning: (near initialization for `PROGMEM') mod_time01.c:79: warning: excess elements in scalar initializer mod_time01.c:79: warning: (near initialization for `PROGMEM') mod_time01.c:79: warning: excess elements in scalar initializer mod_time01.c:79: warning: (near initialization for `PROGMEM') mod_time01.c:79: warning: excess elements in scalar initializer mod_time01.c:79: warning: (near initialization for `PROGMEM') mod_time01.c:79: warning: excess elements in scalar initializer mod_time01.c:79: warning: (near initialization for `PROGMEM') mod_time01.c:79: warning: data definition has no type or storage class
anfaeger schrieb: > MSPGCC Wäre vielleicht sinnvoll gewesen, deinen Controller am Anfang zu erwähnen ...
Na ja, so speziell ist MSPGCC ja nun auch wieder nicht. Gibt es einen Tipp für die Anpassung des Codes, damit er vom MSPGCC akzeptiert wird ? Danke.
Entferne PROGMEM. Entferne pgm_read_byte(& und natürlich die schließende Klammer Die Begriffe sorgen beim AVR dafür, dass die Tabellen im Flash abgespeichert werden, Stichwort Harvard-Struktur. Ohne Begriffe funktioniert es auch, es kann sein, dass die Daten dann im RAM abgelegt werden (weiß nicht wie das der MSPGCC macht).
Ok, jetzt habe ich "PROGMEM" weggelassen, dann wird der Code compiliert, aber beim Linken wird noch dieser Fehler angezeigt : mod_time01.o: In function `gettime': mod_time01.c:(.text+0x24a): undefined reference to `pgm_read_byte' mod_time01.c:(.text+0x254): undefined reference to `pgm_read_byte' c:\mspgcc\bin\make.exe: *** [main_F24x_SIM900_test01.elf] Error 1 Wahrscheinlich ist "pgm_read_byte" beim AVR auch irgendwo definiert ? P.S. Wozu ist "PROGMEM" beim AVR gut ?
Floh schrieb: > Entferne pgm_read_byte(& und natürlich die schließende Klammer anfaenger schrieb: > P.S. Wozu ist "PROGMEM" beim AVR gut ? Augen auf? Floh schrieb: > Die Begriffe sorgen beim AVR dafür, dass die Tabellen im Flash > abgespeichert werden, Stichwort Harvard-Struktur. > > Ohne Begriffe funktioniert es auch, es kann sein, dass die Daten dann im > RAM abgelegt werden (weiß nicht wie das der MSPGCC macht). Google kaputt? http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html
@Floh und Bernhard : Danke, unsere Posts haben sich überschnitten jetzt schluckt der Compiler den Code. Mal sehen, ob auch das korrekte Datum berechnet wird.
anfaenger schrieb: > @Floh und Bernhard : Danke, unsere Posts haben sich überschnitten jetzt > schluckt der Compiler den Code. > Mal sehen, ob auch das korrekte Datum berechnet wird. sollte schon...ich kann das Sourcefile, aus dem der code ist auch auf Unix übersetzen, und da kommt das richtige raus... (natürlich nicht bei negativen Zahlen, Unix setzt negative time_t Zeiten in vor-1970 um, mein Code arbeitet mit unsigned und geht deshalb weiter als bis 2038...)
anfaenger schrieb: > @Floh und Bernhard : Danke, unsere Posts haben sich überschnitten jetzt > schluckt der Compiler den Code. > Mal sehen, ob auch das korrekte Datum berechnet wird. Dann entschuldige ich mich für meinen offensiven Post!
Echt klasse ! Damit hat sich auch das NTP-Problem aus diesem Thread erledigt : Beitrag "Zeit von ntp-Server abrufen;" Für die Unix-Zeit 1336550777 liefert der Code von Bernhard den korrekten UTC Datum/Zeit-Wert 20120509 08:06:17 (JJJJMMTT HH:MM:SS) Ich war schon ziemlich genervt, weil die Zeiten eines ntp-Servers ja prinzipiell im UTC-Format übermittelt werden sollten, mir dieser Link http://www.aritso.net/aritso-tools/timestampconverter/ aus dem Unix-Zeitwert aber immer UTC+1 (=MEZ) berechnet hat (auch wenn UTC vorgegeben war) Das Ergebnis lautet z.B. für die oben verwendete Unix-Zeit "Der Timestamp 1336550777 entspricht dem 09.05.2012 um 09:06:17 Uhr. (gilt für UTC 0)" THX ! P.S. @Simon K. : Kein Problem, mir war schon klar, dass Du das mit der Überschneidung nicht wissen konntest.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.