von
kremsy (Gast)
21.05.2012 20:16
Hallo Leute,
Habe ein STM32F10x Discovery Board mit einer Battery für die dauernde
fortsetzung der echtzeituhr.
Wie im Beispiel wird so die Zeit bei 25.00 (0Uhr) zureückgesetzt:
1 /* Reset RTC Counter when Time is 23:59:59 */
2 if ( RTC_GetCounter () == 0x0001517F )
3 {
4 RTC_SetCounter ( 0x0 );
5 /* Wait until last write operation on RTC registers has finished */
6 RTC_WaitForLastTask ();
7 }
Aber es wird nicht zurückgesetzt während es Batteriebetrieben ist, gibt
es eine möglichkeit dass das auch zurückgesetzt wird während das system
im Batterie betrieb läuft?
mfg kremsy
von
holger (Gast)
21.05.2012 20:37
>Aber es wird nicht zurückgesetzt während es Batteriebetrieben ist, gibt
>es eine möglichkeit dass das auch zurückgesetzt wird während das system
>im Batterie betrieb läuft?
Wenn wer im Batteriebetrieb läuft? Nur die RTC?
Dann geht das nicht.
von
kremsy (Gast)
21.05.2012 20:40
Will einfach dass wenn jetzt 24h Poweroff is die zeit noch stimmt.
Kann man zum Beispiel den Zählwert beim wechsel in den batterymode
sichern oder sowas?
von
holger (Gast)
21.05.2012 21:13
>Will einfach dass wenn jetzt 24h Poweroff is die zeit noch stimmt.
Das tut sie. Die RTC zählt einfach nur weiter als einen Tag.
Wenn du sie ausliest und nur eine 24h Anzeige willst dann machst du
halt:
time = RTC_GetCounter() % 86400;
von
kremsy (Gast)
23.05.2012 16:24
time = RTC_GetCounter() % 86400; kann nicht ganz stimmen.
bsp. 80000%86400=80000
Sinnvoller wäre RTC_GetCounter()/3600 % 86400; das stimmt aber auch nur
für die ersten 24h.
Man bräuchte irgenteine formel um von RTC_GetCounter() ein vielfaches
der stunden in 24 rauszubekommen.
von
kremsy (Gast)
23.05.2012 16:25
Ah habs verstanden, stunden sind einfach (RTC_GetCounter()%86400)/3600
;).
Ich habe es damals so gelöst wie in dem Programmsnip. Man bekommt damit
die Anzahl der Tage raus, wo der RTC lief und kann auch gleich noch ein
Datum mitführen. Das ist jedoch nur ein Programmauszug als Denkanstoß.
Für Datum kommt man an der Nutzung der BKP Register nicht herum. 1 #define RTC_SEKUNDEN_TAG 86400 /* Sekunden pro Tag */
2
3 // ***********************************************************************
4 // RTC Datumskorrektur nach Netzausfall
5 // ***********************************************************************
6 void rtc_datumskorrektur ( void ) {
7 uint16_t tage ;
8
9 zeit . counter_temp = RTC_GetCounter (); // RTC Sekundenzähler
10
11 if (( zeit . counter_temp / RTC_SEKUNDEN_TAG ) != 0 ) {
12 // Mindestens 1 Datumsübertrag
13 for ( tage = 0 ; tage < ( zeit . counter_temp / RTC_SEKUNDEN_TAG ); tage ++ ) {
14 rtc_inc_datum (); // Datum um einen Tag erhöhen
15 }
16 RTC_SetCounter ( zeit . counter_temp % RTC_SEKUNDEN_TAG );
17 }
18 }
19
20 ...
21
22 // ***********************************************************************
23 // RTC Datum um einen Tag erhöhen
24 // Überträge auf Monat und Jahr
25 // Schaltjahr (4-Jahresregel Regel) wird beachtet
26 // ***********************************************************************
27 void rtc_inc_datum ( void ) {
28 uint8_t temp_tage ;
29
30 // Wochentag aktualisieren
31 if ( zeit . wo_tag < 6 ) {
32 // Wochentag erhöhen
33 zeit . wo_tag ++ ;
34 } else {
35 zeit . wo_tag = 0 ;
36 }
37
38 // Anzahl der Tage des Monats
39 switch ( zeit . monat ) {
40 case 2 : // Monat Februar mit 28 Tagen ggf. mit Schaltjahr 29
41 temp_tage = 28 ;
42 // Schaltjahr Prüfung
43 if ( ! ( zeit . jahr % 4 )) {
44 // Schaltjahr (nur 4-Jahres-Zyklus Regel beachtet)
45 // 400/100 Regel erst wieder im Jahr 2100 von Bedeutung!!!
46 temp_tage = 29 ;
47 }
48 break ;
49 case 4 : // Monate mit 30 Tagen
50 case 6 :
51 case 9 :
52 case 11 : // April, Juni, September, November
53 temp_tage = 30 ;
54 break ;
55 default: // Monate mit 31 Tagen (alle nicht mit case ausselektierten!)
56 // Januar, März, Mai, Juli, August, Oktober, Dezember
57 temp_tage = 31 ;
58 }
59
60 // Datum aktualisieren
61 if ( zeit . tag < temp_tage ) {
62 // Tag erhöhen
63 zeit . tag ++ ;
64 } else {
65 // neuer Monat
66 zeit . tag = 1 ; // Tag = 1
67 if ( zeit . monat < 12 ) {
68 // Monat erhöhen
69 zeit . monat ++ ;
70 } else {
71 // neues Jahr
72 zeit . monat = 1 ;
73 zeit . jahr ++ ;
74 }
75 }
76 }
von
kremsy (Gast)
23.05.2012 16:41
1 void RTC_Cyclic_1Sec ( void )
2 {
3 char res [ 2 ];
4 uint32_t time ;
5 time = RTC_GetCounter () % 86400 ;
6 /* Reset RTC Counter when Time is 23:59:59 */
7 // if (RTC_GetCounter() == 0x0001517F)
8 if ( time == 0 && RTC_GetCounter () != 0 )
9 {
10 RTC_SetCounter ( 0x0 );
11 /* Wait until last write operation on RTC registers has finished */
12 RTC_WaitForLastTask ();
13 }
14 if ( TimeDisplay == 1 )
15 {
16 lcd_setcursor ( 2 , 2 );
17 UTIL_uint2str ( res , ( time / 3600 ) , 2 , 0 ); //hour
18 lcd_string ( res );
19 LCD_Data ( ':' );
20 UTIL_uint2str ( res , ( time / 3600 ) / 60 , 2 , 1 ); //min
21 lcd_string ( res );
22 LCD_Data ( ':' );
23 UTIL_uint2str ( res , ( time / 3600 ) % 60 , 2 , 1 ); //sec
24 lcd_string ( res );
25 TimeDisplay = 0 ;
26 }
27 }
liefter 0:0:0 am display seit ich das mit der time so gemacht habe.
Jemand ne ahnung was falsch ist?
von
kremsy (Gast)
23.05.2012 16:49
Danke matthias für deinen tollen Denkanstoß, werds mir bei gelegenheit
näher anschaun. das BKP register nutze ich sowiso schon, von daher kein
Problem.
Aber versteh grad net wo mein Denkfehler im aktuellen code liegt.
von
kremsy (Gast)
23.05.2012 16:50
Ah wahrscheinlich brauchts nur nen typcast.
von
kremsy (Gast)
23.05.2012 17:01
1 void RTC_Cyclic_1Sec ( void )
2 {
3 char res [ 2 ];
4 /* Reset RTC Counter when Time is 23:59:59 */
5 if ( RTC_GetCounter () == 0x0001517F )
6 {
7 RTC_SetCounter ( 0x0 );
8 /* Wait until last write operation on RTC registers has finished */
9 RTC_WaitForLastTask ();
10 }
11 if ( TimeDisplay == 1 )
12 {
13 lcd_setcursor ( 2 , 2 );
14 UTIL_uint2str ( res , ( RTC_GetCounter () % 86400 ) , 2 , 0 ); //hour
15 lcd_string ( res );
16 LCD_Data ( ':' );
17 UTIL_uint2str ( res , ( RTC_GetCounter () % 3600 ) / 60 , 2 , 1 ); //min
18 lcd_string ( res );
19 LCD_Data ( ':' );
20 UTIL_uint2str ( res , ( RTC_GetCounter () % 3600 ) % 60 , 2 , 1 ); //sec
21 lcd_string ( res );
22 TimeDisplay = 0 ;
23 }
24 }
25
26 Wohl zuviel ge ä ndert ;)
27
28 Neue code der funktionieren sollte :
29 void RTC_Cyclic_1Sec ( void )
30 {
31 char res [ 2 ];
32 uint32_t time ;
33 time = RTC_GetCounter () % 86400 ;
34 /* Reset RTC Counter when Time is 23:59:59 */
35 // if (RTC_GetCounter() == 0x0001517F)
36 if ( time == 0 && RTC_GetCounter () != 0 )
37 {
38 RTC_SetCounter ( 0x0 );
39 /* Wait until last write operation on RTC registers has finished */
40 RTC_WaitForLastTask ();
41 }
42 if ( TimeDisplay == 1 )
43 {
44 lcd_setcursor ( 2 , 2 );
45 UTIL_uint2str ( res , ( time / 3600 ) , 2 , 0 ); //hour
46 lcd_string ( res );
47 LCD_Data ( ':' );
48 UTIL_uint2str ( res , ( time % 3600 ) / 60 , 2 , 1 ); //min
49 lcd_string ( res );
50 LCD_Data ( ':' );
51 UTIL_uint2str ( res , ( time % 3600 ) % 60 , 2 , 1 ); //sec
52 lcd_string ( res );
53 TimeDisplay = 0 ;
54 }
55 }
Klappt es nun?
Ich mache die Zeit- und Datumaufbereitung generell im Interrupt
(RTC_IRQHandler) und stelle es alles in einer Struktur dem Hauptprogramm
zur Verfügung. Dort erfolgt auch die Anzeige auf LCD oder TFT.
etwas so: 1 //***********************************************************************************************
2 // RTC Interrupt-Handler
3 // Laufzeiten: 5us / Sekunde (100us für kompletten Jahreswechsel)
4 // bei 72MHz
5 //***********************************************************************************************
6 void RTC_IRQHandler ( void ) {
7 unsigned char temp_tage ;
8
9 if ( RTC_GetITStatus ( RTC_IT_SEC ) != RESET ) {
10 // RTC neue Sekunde
11 RTC_ClearITPendingBit ( RTC_IT_SEC ); // Sekunden-Interrupft-Flag löschen
12 RTC_WaitForLastTask (); // auf RTC-Bereitschaft warten
13
14 zeit . counter_temp = RTC_GetCounter (); // RTC Sekundenzähler
15 RTC_WaitForLastTask ();
16
17 // Prüfung auf Datumswechsel (24:00:00)
18 if ( zeit . counter_temp == RTC_SEKUNDEN_TAG ) {
19 RTC_SetCounter ( 0x1 ); // RTC Sekundenzähler zurücksetzen
20 RTC_WaitForLastTask ();
21 zeit . counter_temp = 0 ;
22
23 // Wochentag aktualisieren
24 if ( zeit . wo_tag < 6 ) {
25 // Wochentag erhöhen
26 zeit . wo_tag ++ ;
27 } else {
28 zeit . wo_tag = 0 ;
29 }
30
31 // Anzahl der Tage des Monats
32 switch ( zeit . monat ) {
33 case 2 : // Monat Februar mit 28 Tagen ggf. mit Schaltjahr 29
34 temp_tage = 28 ;
35 // Schaltjahr Prüfung
36 if ( ! ( zeit . jahr % 4 )) {
37 // Schaltjahr (nur 4-Jahres-Zyklus Regel beachtet)
38 // 400/100 Regel erst wieder im Jahr 2100 von Bedeutung!!!
39 temp_tage = 29 ;
40 }
41 break ;
42 case 4 : // Monate mit 30 Tagen
43 case 6 :
44 case 9 :
45 case 11 : // April, Juni, September, November
46 temp_tage = 30 ;
47 break ;
48 default: // Monate mit 31 Tagen (alle nicht mit case ausselektierten!)
49 // Januar, März, Mai, Juli, August, Oktober, Dezember
50 temp_tage = 31 ;
51 }
52
53 // Datum aktualisieren
54 if ( zeit . tag < temp_tage ) {
55 // Tag erhöhen
56 zeit . tag ++ ;
57 } else {
58 // neuer Monat
59 zeit . tag = 1 ; // Tag = 1
60 if ( zeit . monat < 12 ) {
61 // Monat erhöhen
62 zeit . monat ++ ;
63 } else {
64 // neues Jahr
65 zeit . monat = 1 ;
66 zeit . jahr ++ ;
67 }
68 }
69 }
70
71 // Uhrzeit aktualisieren
72 zeit . stunde = zeit . counter_temp / 3600 ;
73 zeit . minute = ( zeit . counter_temp % 3600 ) / 60 ;
74 zeit . sekunde = ( zeit . counter_temp % 3600 ) % 60 ;
75
76 // Backupregister aktualisieren
77 BKP_WriteBackupRegister ( BKP_DR2 , zeit . tag );
78 BKP_WriteBackupRegister ( BKP_DR3 , zeit . monat );
79 BKP_WriteBackupRegister ( BKP_DR4 , zeit . jahr );
80 BKP_WriteBackupRegister ( BKP_DR5 , zeit . wo_tag );
81 BKP_WriteBackupRegister ( BKP_DR6 , zeit . mesz );
82
83 // Meldung an das Hauptprogramm, dass neue Zeit vorhanden ist.
84 zeit . update = 1 ;
85 }
86 }
87
88 .....
89
90 // Systemzeit-Struktur
91 struct zeit_struc {
92 volatile uint32_t counter_temp ; // RTC-Counter (Snap)
93 volatile uint16_t jahr ; // Jahr 4 stellen
94 volatile uint8_t monat ; // Monat 1-12
95 volatile uint8_t tag ; // Tag 1-31
96 volatile uint8_t stunde ; // 0-23
97 volatile uint8_t minute ; // 0-59
98 volatile uint8_t sekunde ; // 0-59
99 volatile uint8_t wo_tag ; // 0-6
100 volatile uint8_t mesz ; // Sommerzeit 1=MESZ(Sommerzeit) 0=MEZ(Winter)
101 volatile uint8_t update ; // 1=Neue Sekunde
102 volatile uint8_t set ; // 1=Uhrzeit stellen
103 };
104 struct zeit_struc zeit ; // Systemzeit Variablen
von
kremsy (Gast)
23.05.2012 22:20
Jap klappt alles, wenn ich Zeit habe werde ich es vielleicht auch so
Umsetzen wie du ;).
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.