Forum: Mikrocontroller und Digitale Elektronik Zeit und Datum aus Unix-Zeit, schlanker Code gesucht;


von anfaenger (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

Sourcecode von gmtime() suchen.

von Mitesser (Gast)


Lesenswert?

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.

von Bernhard M. (boregard)


Lesenswert?

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
}

von (prx) A. K. (prx)


Lesenswert?

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)])))

von Bernhard M. (boregard)


Lesenswert?

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 ;-)

von anfaeger (Gast)


Lesenswert?

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

von Floh (Gast)


Lesenswert?

anfaeger schrieb:
> MSPGCC

Wäre vielleicht sinnvoll gewesen, deinen Controller am Anfang zu 
erwähnen ...

von Bernhard M. (boregard)


Lesenswert?

..der Code war nämlich für AVR...

aber diese Kleinigkeit solltest Du selbst umschreiben können...

von anfaenger (Gast)


Lesenswert?

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.

von Floh (Gast)


Lesenswert?

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).

von anfaenger (Gast)


Lesenswert?

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 ?

von Simon K. (simon) Benutzerseite


Lesenswert?

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

von anfaenger (Gast)


Lesenswert?

@Floh und Bernhard : Danke, unsere Posts haben sich überschnitten jetzt 
schluckt der Compiler den Code.
Mal sehen, ob auch das korrekte Datum berechnet wird.

von Bernhard M. (boregard)


Lesenswert?

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...)

von Simon K. (simon) Benutzerseite


Lesenswert?

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!

von anfaenger (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.