mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik STM32 Uhrzeit des RTC Umrechnen


Autor: Markus Müller (mmvisual)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Der STM32 liefert eine Uhrzeit als 32-Bit Zähler, der jede Sekunde eine 
Zahl hoch zählt.

Es wurde schon einige male erwähnt, die Umrechnungsroutinen in D.M.Y 
h:n:s und zurück gibt es zu hauf im Netz.
Jetzt hab ich mal danach gesucht weil ich sowas brauche, aber nichts 
gefunden.

Könnt Ihr mir helfen wo ich sowas finden kann?
Oder mir ein Demo Posten?

Vielen Dank im Voraus.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für timestamp => DD.MM.YY/HH.MM.DD nach Sourcecode der in C üblichen 
Libfunktionen localtime() oder gmtime() suchen (mal basiert localtime 
auf gmtime, mal ist es andersrum).

Beispielsweise (ggf. auf © achten) 
http://www.raspberryginger.com/jbailey/minix/html/...

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für die umgekehrte Richtung siehe mktime(), diesmal aus dem Linux 
Kernel:
http://www.linuxhq.com/kernel/v1.0/0/kernel/mktime.c

Beides sollte man aber auch ganz gut selber zustande kriegen. Jedenfalls 
wenn man sich das Leben nicht mit UTC und Sommerzeit erschwert.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Jedenfalls
> wenn man sich das Leben nicht mit UTC und Sommerzeit erschwert.

Sag bloß, Deine Uhren gehen jetzt alle eine Stunde nach.

Was ist denn an Sommerzeit so schwierig?

Beitrag "Berechnung Datum + Uhrzeit + Sommerzeit"


Peter

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger schrieb:

> Was ist denn an Sommerzeit so schwierig?

Die Politik. Die Definition davon ändert sich ab und zu und dann darfst 
du alle Steuerungen ohne Funkuhr mit neuer Firmware versehen. Vor allem 
wenn das auch international funktionieren soll.

Autor: Markus Müller (mmvisual)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, meine Uhr hab ich schon richtig gerechnet, das tut.
Nur läuft die noch mit dem System-Timer und ich habe heute die Hardware 
umgebaut mit einem Goldcap und einem 32KHz Quarz. Denn bei kurzem 
Stromausfall würde das ja einige Zeit weiter laufen. Ich speichere 
derzeit jede Minutenänderung in das EEPROM und nutze dafür 24 
Speicheradresse. Ist aber eine lästig rechnerei. (20 Jahre würde das gut 
gehen)

Ich habe von ST das AN2821 gefunden, aber die nutzen den RTC Timer nur 
für 86400 Sekunden (1 Tag) der Rest wird als feste Zahl "Manuell" 
gerechnet. Ist nicht ganz das was ich wollte.

@A. K. (prx)
Das ist genau das was ich suchte, vielen Dank!

Sommer/Winterzeit finde ich auch Quatsch. Ich stehe auf, wanns mir 
passt, gehe schlafen wanns mir passt und arbeiten wanns passt 
(Stempeluhr).
(Ich habe auch nie eine Uhr bei mir, ausser der PC ist an.)

Autor: Markus Müller (mmvisual)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe mal was zusammen gebastelt, sollte tun:

als FIRSTYEAR kann eine Zahl rein geschrieben werden, wie man mag. Die 
Linux-Berechnung war starr auf 1970, ich musste noch einiges anpassen.
#define   FIRSTYEAR  2010

typedef struct
{
  u8  Sec;       // Sekunde
  u8  Min;       // Minute
  u8  Hour;      // Stunde
  u8  Day;       // Tag
  u8  Month;     // Monat
  u16 Year;      // Jahr
  u16 YDay;      // Tage im Jahr (0 = 1.1.xxxx)
  u8  WDay;      // Wochentag (0 = Montag)
  u8  IsLeapYear;// Schaltjahr
} time_st;

////////////////////////////////

u8 IsLeapYear(u16 year)
{
  if ((year % 100) == 0)
  {
    if ((year % 400) == 0)
      return 1;
    else return 0;
  }
  if ((year % 4) == 0)
    return 1;
  return 0;
}

time_st Uhr_GetTime(u32 clockval)
{
  const u8 _ytab[2][12] = {{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }};
  time_st ret;
  ret.Sec = clockval % 60;
  ret.Min = (clockval % 3600) / 60;
  ret.Hour = (clockval % 86400) / 3600;
  u32 dayno = clockval / 86400; // Ganzer Tag
  ret.WDay = (dayno + 4) % 7;  // Korrektur bis Montag
  u32 year = FIRSTYEAR;
  while (dayno >= (IsLeapYear(year) ? 366 : 365))
  {
    dayno -= (IsLeapYear(year) ? 366 : 365);
    year++;
  }
  ret.Year = year;
  ret.YDay = dayno;
  ret.IsLeapYear = IsLeapYear(year);
  ret.Month = 0;
  while (dayno >= _ytab[ret.IsLeapYear][ret.Month])
  {
    dayno -= _ytab[ret.IsLeapYear][ret.Month];
    ret.Month++;
  }
  ret.Month++;
  ret.Day = dayno + 1;
  return ret;
}

// Errechnet aus Jahr, Monat, Tag, Stunde, Minute, Sekunde die aktuelle Sekunden-Ticks
u32 Uhr_GetClock(time_st * timeval)
{
#define MINUTE 60
#define HOUR (60*MINUTE)
#define DAY (24*HOUR)
#define YEAR (365*DAY)
  const u32 month[12] = {
     0,
     DAY*(31),
     DAY*(31+28),
     DAY*(31+28+31),
     DAY*(31+28+31+30),
     DAY*(31+28+31+30+31),
     DAY*(31+28+31+30+31+30),
     DAY*(31+28+31+30+31+30+31),
     DAY*(31+28+31+30+31+30+31+31),
     DAY*(31+28+31+30+31+30+31+31+30),
     DAY*(31+28+31+30+31+30+31+31+30+31),
     DAY*(31+28+31+30+31+30+31+31+30+31+30)
  };
  u32 res;
  u16 year;
  res = YEAR * (timeval->Year - FIRSTYEAR);
  year = FIRSTYEAR;
  while (year < timeval->Year)  // Korrektur Schaltjahre
  {
    res += (DAY * IsLeapYear(year));
    year++;
  }
  if (timeval->Month > 2)  // aktuelles Jahr ist Schaltjahr
    res += (DAY * IsLeapYear(timeval->Year));
  res += month[(timeval->Month - 1)];
  res += DAY * (timeval->Day - 1);
  res += HOUR * timeval->Hour;
  res += MINUTE * timeval->Min;
  res += timeval->Sec;
  return res;
}

(Ich weiß, ich hätte auch Code anhängen können, der ist aber nicht sooo 
riesig.)

Autor: Markus Müller (mmvisual)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube die Zeile
"ret.WDay = (dayno + 4) % 7;  // Korrektur bis Montag"
tut nur richtig wenn als Jahr 2010 parametriert ist. Bei einem anderen 
Jahr muss der Offset "4" angepasst werden.

Autor: Markus Müller (mmvisual)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch was fehlt:

Sommer-/Winterzeitumschaltung.
Die beiden Funktionen sollten so arbeiten, dass der RTC-Clock immer mit 
der "Normalzeit" == Winterzeit zählt. Aber die Umwandlung in/von 
Tag/Mon/J Stunde usw. sollte automatisch die Zeit korrigieren. Einzige: 
Wenn Sommer auf Winterzeit umschaltet, während 2:00..3:00 ist die 
Wandlung nicht so einfach möglich, da die Routine nicht erkennen kann ob 
Sommer oder Winterzeit gemeint ist.

Vorteil: - Bei Protokollierung wird der Zeitstempel immer als 32-Bit 
Integer mit "Normalzeit" gesetzt. Also auch bei Zeitumschaltung wird der 
Zeitstempel korrekt gesetzt.
- Niemand muss den RTC Counter manipulieren.

Nachteil: Jeder Zeile einer Protokollierung muss für die 
Bildschirmdarstellung gewandelt werden. Aber das ist ja ohnehin egal.

Ich finde das RTC Prinzip von STM32 genial, weil ich nur noch eine 
32-Bit-Variable behandeln muss...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auf welchem Compiler/Rechner bist du genau?

Das hier wird auf den meisten 16 Bit Compilern in die Hose gehen

#define MINUTE 60
#define HOUR (60*MINUTE)
#define DAY (24*HOUR)

     DAY*(31+28+31+30+31+30+31+31+30+31+30)

Nach dem Präprozessor steht da

    24*(60*(60))*(31+28+31+30+31+30+31+31+30+31+30)

Lauter int.
Die Berechnung wird daher als int-Multiplikation gemacht und bei 16-Bit 
int läuft das über.
24*60*60 ergibt bereits 86400, also viel zu viel für einen int.

Autor: Markus Müller (mmvisual)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
WinXP/GCC/Coudesourcery

Die Definition ist "u32". Dies ist in der STM FW-Lib garantiert 32 Bit 
groß.

Dieses Codefragment wurde von "A. K. (prx)" gepostet und existiert 
bereits seit 1993 in den Linux-Sourcen.

Bei mir klappt das richtig, ich habe das getestet bis Dez. 2027. Beide 
Funktionen im Wechsel aufgerufen und die Zahlen bleiben gleich.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:

> Auf welchem Compiler/Rechner bist du genau?

Der STM32, um den es laut Betreff-Zeile geht, ist ein 32-Bitter. Das 
kann dir eigentlich in den letzten Monaten kaum verborgen geblieben 
sein. ;-)

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Markus Müller schrieb:

> Die Definition ist "u32". Dies ist in der STM FW-Lib garantiert 32 Bit
> groß.

Schon, aber
  u32 var = 1000*1000;
geht bei einem 16-Bit Prozessor trotzdem in die Hose. Weil 1000*1000 
auch auch dann als "int" gerechnet wird, wenn u32 1024 Bit breit sein 
sollte.

Autor: Markus Müller (mmvisual)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zum Glück mache ich um 8/16-Bitter einen weiten Bogen :)

Autor: Rainer K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi! Also erst mal danke für die Bereitstellung des Codes, ich versuche 
mich quasi gerade an der selben Thematik. Bin deinen Code mal 
durchgegangen, ich steige aber Teilweise nicht dahinter.

Diese Condition:

if (timeval->Month > 2)  // aktuelles Jahr ist Schaltjahr

Wieso gibt Month > 2 Aufschluß darüber ob es sich beim Datum um ein 
Schaltjahr handelt?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tut es nicht. Code/Kommentar-Schere. Es gibt Auskunft, ob es mindestens 
März ist. Für die Korrektur wg. Schaltjahr sorgt die Zeile danach.

Autor: Matthias K. (matthiask)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei STM gibt es eine gute AppNote zum RTC:
RTC AN2821 Clock/calendar implementation on the STM32F10xxx 
microcontroller
http://www.st.com/mcu/familiesdocs-110.html#Applic...

Auch in den EVAL Beispielen findet sich einiges.

Autor: Rainer K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ A.K. Stimmt... ich persönlich würde erst prüfen ob es ein Schaltjahr 
ist und dann ob es März ist, finde ich verständlicher und spart in der 
Mehrheit der fälle einen funktionsaufruf. Aber ja... man sollte den code 
genau lesen bevor man sich hier beschwert. Danke für den Hinweis.

@ Matthis K.
Danke für den Hinweis, ich hatte in der Driver Lib keine direkten 
Funktionen dazu gefunden und bin davon ausgegangen dass es zu dem Thema 
von ST nichts gibt. Das einzige Beispiel, dass in den Lib examples 
enthalten war Rechnet nur mit jeweils einem Tag... Und das bekommt man 
auch noch so hin.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Markus Müller schrieb:
> Zum Glück mache ich um 8/16-Bitter einen weiten Bogen :)

Das läuft doch prima auf nem 8-Bitter:

Beitrag "Berechnung Datum + Uhrzeit + Sommerzeit"

Mir reicht es, einen 8-Bitter zu 99% zu langweilen, als nen 32-Bitter zu 
99,9%.

Hauptsache, ich muß nicht so viele Beinchen löten und externen Krams 
(Spannungsregler usw.).


Peter

Autor: Martin Thomas (mthomas) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Evtl. hilfreich: Die von Peter Dannegger und "LalaDumm" im o.g. Thread 
bereitgestellten Codes sind in den RTC-Routinen einer meiner STM32 
Beispielanwendungen enthalten:
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm...

Autor: ARi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

beim Ausprobieren des Bsp.-Codes jetzt im Februar hatte ich beim Wandeln 
mit "struct_to_counter" und zurück mit "counter_to_struct" eine 
Differenz von einem Tag. Beim Durchsehen der Quellen ist mir dann ein 
"Verschönerungs"-Fehler aufgefallen.

Ausschnitt aus "struct_to_counter"

/* Make month an array index */
  idx = t->month - 1;

  /* Loop thru each month, adding the days */
  for (i = 0; i < idx; i++) {
    result += DaysInMonth[i];
  }

  /* Leap year? adjust february */
  if (!isLeapYear(year)) {
    if (t->month > 1) {
    result--;
    }
  }

in der Abfrage "if (t->month > 1)" weiterhin den "idx" verwenden, so 
wars vermutlich mal, oder den Wert auf "2"(für Februar) erhöhen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.