Forum: Mikrocontroller und Digitale Elektronik STM32 RTC CLOCK


von Andre (Gast)


Lesenswert?

Hallo,
Habe ein STM32F10x Discovery Board mit einer Battery für die fortsetzung 
der Echtzeituhr.

Wenn ich z.B. die Uhr auf 23:59:45 stelle und ziehe den Strom-stecker 
dann
sollte ja die interne Uhr ja weiterlaufen
warte ich 20 sekunden stecker wieder rein , nur leider wird dann nicht
00:00:00 angezeigt sondern 25:00:00
vielleicht könnte mir einer vohn ihnen weiterhelfen.
1
    // Uhrzeit Voreinstellen
2
    u32 tmp;
3
    zeit.stunde  = 23;
4
    zeit.minute  = 59;
5
    zeit.sekunde = 45;
6
7
    tmp = ((zeit.stunde * 3600)+ (zeit.minute * 60)+zeit.sekunde);
8
9
    RTC_WaitForLastTask();
10
    RTC_SetCounter(tmp ); 
11
    RTC_WaitForLastTask();
12
13
14
void RTC_IRQHandler (void) {
15
unsigned char temp_tage;
16
17
  if (RTC_GetITStatus(RTC_IT_SEC) != RESET) {
18
    // RTC neue Sekunde
19
    RTC_ClearITPendingBit(RTC_IT_SEC);      // Sekunden-Interrupft-Flag löschen
20
    RTC_WaitForLastTask();                  // auf RTC-Bereitschaft warten
21
22
    zeit.counter_temp = RTC_GetCounter();   // RTC Sekundenzähler
23
    RTC_WaitForLastTask();
24
25
    // Prüfung auf Datumswechsel (24:00:00)
26
    if (zeit.counter_temp == RTC_SEKUNDEN_TAG) {
27
      RTC_SetCounter(0x1);                  // RTC Sekundenzähler zurücksetzen
28
      RTC_WaitForLastTask();
29
      zeit.counter_temp = 0;
30
31
      // Wochentag aktualisieren
32
      if (zeit.wo_tag < 6) {
33
        // Wochentag erhöhen
34
        zeit.wo_tag++;
35
      } else {
36
        zeit.wo_tag = 0;
37
      }
38
39
      // Anzahl der Tage des Monats
40
      switch (zeit.monat) {
41
        case  2: // Monat Februar mit 28 Tagen ggf. mit Schaltjahr 29
42
                 temp_tage = 28;
43
                 // Schaltjahr Prüfung
44
                 if (!(zeit.jahr % 4)) {
45
                   // Schaltjahr (nur 4-Jahres-Zyklus Regel beachtet)
46
                   // 400/100 Regel erst wieder im Jahr 2100 von Bedeutung!!!
47
                   temp_tage = 29;
48
                 }
49
                 break;
50
        case  4: // Monate mit 30 Tagen
51
        case  6:
52
        case  9:
53
        case 11: // April, Juni, September, November
54
                 temp_tage = 30;
55
                 break;
56
        default: // Monate mit 31 Tagen (alle nicht mit case ausselektierten!)
57
                 // Januar, März, Mai, Juli, August, Oktober, Dezember
58
                 temp_tage = 31;
59
      }
60
61
      // Datum aktualisieren
62
      if (zeit.tag < temp_tage) {
63
        // Tag erhöhen
64
        zeit.tag++;
65
      } else {
66
        // neuer Monat
67
        zeit.tag = 1; // Tag = 1
68
        if (zeit.monat < 12) {
69
          // Monat erhöhen
70
          zeit.monat++;
71
        } else {
72
          // neues Jahr
73
          zeit.monat = 1;
74
          zeit.jahr++;
75
        }
76
      }
77
    }
78
79
    // Uhrzeit aktualisieren
80
    zeit.stunde  = zeit.counter_temp / 3600;
81
    zeit.minute  = (zeit.counter_temp % 3600) / 60;
82
    zeit.sekunde = (zeit.counter_temp % 3600) % 60;
83
84
    // Backupregister aktualisieren
85
    BKP_WriteBackupRegister(BKP_DR2, zeit.tag);
86
    BKP_WriteBackupRegister(BKP_DR3, zeit.monat);
87
    BKP_WriteBackupRegister(BKP_DR4, zeit.jahr);
88
    BKP_WriteBackupRegister(BKP_DR5, zeit.wo_tag);
89
    BKP_WriteBackupRegister(BKP_DR6, zeit.mesz);
90
91
    // Meldung an das Hauptprogramm, dass neue Zeit vorhanden ist.
92
    zeit.update = 1;
93
  }
94
} 
95
96
// Systemzeit-Struktur
97
struct zeit_struc {
98
  volatile uint32_t counter_temp;   // RTC-Counter (Snap)
99
  volatile uint16_t jahr;           // Jahr 4 stellen
100
  volatile uint8_t  monat;          // Monat 1-12
101
  volatile uint8_t  tag;            // Tag 1-31
102
  volatile uint8_t  stunde;         // 0-23
103
  volatile uint8_t  minute;         // 0-59
104
  volatile uint8_t  sekunde;        // 0-59
105
  volatile uint8_t  wo_tag;         // 0-6
106
  volatile uint8_t  mesz;           // Sommerzeit 1=MESZ(Sommerzeit) 0=MEZ(Winter)
107
  volatile uint8_t  update;         // 1=Neue Sekunde
108
  volatile uint8_t  set;            // 1=Uhrzeit stellen
109
};
110
struct zeit_struc zeit;      // Systemzeit Variablen

von (prx) A. K. (prx)


Lesenswert?

Was passiert wohl, wenn ausgerechnet bei
  zeit.counter_temp == RTC_SEKUNDEN_TAG
der Strom weg ist? Die RTC zählt nämlich munter weiter, aber der 
Interrupt kommt nicht.

Nun kannst du dein
  if (zeit.counter_temp == RTC_SEKUNDEN_TAG) {
natürlich zu einem
  while (zeit.counter_temp >= RTC_SEKUNDEN_TAG) {
     zeit.counter_temp -= RTC_SEKUNDEN_TAG;
umbauen. Und den RTC Counter dann aber nicht auf 0 oder 1 setzen, 
sondern auf das was dabei übrig bleibt.

Eine Alternative zu diesem Ansatz ist die Timestamp-Methode à la Unix. 
Also Sekunden seit Töchterleins Geburt in den RTC Zähler reinschreiben 
und bei Anfrage komplett umrechnen. Gibt erst Probleme, wenn Töchterlein 
der Rente entgegen sieht.

: Bearbeitet durch User
von Andreas (Gast)


Lesenswert?

Danke für ihre Antwort ,
Könnten sie mir vielleicht zu der  Timestamp-Methode à la Unix.  einen 
Link oder Beispiel
Sagen
Danke
Mfg

von (prx) A. K. (prx)


Lesenswert?


von Reinhard Kern (Gast)


Lesenswert?

A. K. schrieb:
> Die RTC zählt nämlich munter weiter, aber der
> Interrupt kommt nicht.

Macht ja nix. Ist der Zähler übergelaufen wegen Stromausfall, dann kann 
man das ja in der Power-On-Routine nach dem Ausfall korrigieren, bevor 
die Zeit irgendwo verwendet wird.

Bequemer ist natürlich eine RTC, die von selbst Sekunden, Minuten, 
Stunden und Tage korrekt zählt und möglichst auch (Schalt-) Jahre. Dann 
muss man sich erst im Februar 2100 drum kümmern.

Gruss Reinhard

von (prx) A. K. (prx)


Lesenswert?

Reinhard Kern schrieb:
> Macht ja nix. Ist der Zähler übergelaufen wegen Stromausfall, dann kann
> man das ja in der Power-On-Routine nach dem Ausfall korrigieren, bevor
> die Zeit irgendwo verwendet wird.

Auch so gehts. Eine andere Version mit nur minimaler Änderung des Codes 
hatte ich oben ja schon selbst skizziert.

> Bequemer ist natürlich eine RTC, die von selbst Sekunden, Minuten,
> Stunden und Tage korrekt zählt und möglichst auch (Schalt-) Jahre. Dann
> muss man sich erst im Februar 2100 drum kümmern.

Mal ist die eine Version praktischer, mal die andere. Wenn du nach 
Ablauf einer bestimmten Zeit wieder aufwachen willst, also 30 Sekunden 
von jetzt. dann ist die Binärzähler-Version bequemer. Aber sobald man 
die beiden Konvertierfunktionen mal im Griff hat ist es schnuppe, wie 
die Hardware zählt.

von Andreas (Gast)


Lesenswert?

Vielen Dank für den Tip mit der Unix,
von ST gibs dazu auch ein Bespiel welches ich jetzt nutze das sehr gut 
Funktioniert
Danke nochmals.

von Artur (Gast)


Lesenswert?

Hey Leute :)
hat vl jemand von euch einen Code für das STM32f1 mit dem ich eine eine 
RTC laufen lasse. Ich würde gerne mit 2 Tasten Minuten plus 1 und 
stunden plus 1 erhöhen.

Würde mich sehr freuen wenn ihr mir helfen könntet.!

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.