Ich versuche, an einem STM32F103 die RTC mit dem 32-kHz-Quarz in Betrieb
zu nehmen.
Ich habe mir aus Datenblatt sowie Beispielcode das hier als
Initialisierung heraus gepuzzelt:
1
voidinit_RTC(void)
2
{
3
PWR->CR|=PWR_CR_DBP;
4
5
while((RTC->CRL&RTC_CRL_RTOFF)==0){/* wait */}
6
RTC->CRL|=RTC_CRL_CNF;
7
8
RTC->PRLH=0;
9
RTC->PRLL=0x7FFF;// 1-second prescaler
10
RTC->CRL&=~RTC_CRL_SECF;
11
RTC->CRH=RTC_CRH_SECIE;
12
13
RTC->CRL&=~RTC_CRL_CNF;
14
15
PWR->CR&=~PWR_CR_DBP;
16
17
while((RTC->CRL&RTC_CRL_RTOFF)==0){/* wait */}
18
19
NVIC_ClearPendingIRQ(RTC_IRQn);
20
NVIC_EnableIRQ(RTC_IRQn);
21
}
Problem: wenn ich das so durchlaufen lasse, wird das RTOFF-Bit in der
zweiten Schleife nie gesetzt. Wenn ich mit dem Debugger
einzelschrittweise durch die Zeilen steppe, bleibt es dagegen die ganze
Zeit gesetzt, und alles funktioniert am Ende wie gewünscht.
Ist also offenbar irgendeine zeitliche Restriktion, die ich übersehen
haben muss, aber welche?
ps: Bitte keine Antworten a la "mit Framework XYZ funktioniert das" –
ich möchte gern die Hardware verstanden haben. Da hilft mir irgendein
Framework nicht.
Ich vermisse das Anschalten des LSE im RCC_BDCR Register (Bit LSEON).
Danach sollte man in einer Schleife nach LSE_RDY fragen, bis der
Oszillator soweit ist. (Im RM0008 auf Seite 115).
Letztlich schaltet man da auch die RTC ein (Bit 15 im RCC_BDCR).
Machst du das woanders?
Matthias S. schrieb:> Machst du das woanders?
Ja, im init_clock() zuvor. Scheint ja auch funktioniert zu haben, denn
wenn ich die obigen Zeilen Einzelschritt durchgehe, dann läuft es ja
hernach wie erwartet.
1
voidinit_clock(void)
2
{
3
// Conf clock : 64MHz using HSE 16MHz crystal w/ PLL X 4 (16MHz x 4 = 64MHz)
4
FLASH->ACR|=FLASH_ACR_LATENCY_2;// Two wait states, per datasheet
Jörg W. schrieb:> Ja, im init_clock() zuvor.
Gut :-)
Hmm, leider bin ich mit der RTC im F103 nicht so bewandert. Ich weiss
nur, das ich beim F429 erst die Clocksource wähle und später dann die
Uhr freigebe:
1
// use the low freq. crystal
2
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
3
RCC_RTCCLKCmd(ENABLE);
Das ist mit SPL, aber das Prinzip bleibt. Vllt. darf man nicht beides
gleichzeitig machen.
Matthias S. schrieb:> Das ist mit SPL, aber das Prinzip bleibt. Vllt. darf man nicht beides> gleichzeitig machen.
Ich glaube, ich hatte das vorher getrennt. Das gemeinsame Setzen habe
ich mir vom Keil-Beispielcode abgeguckt, bisschen in der Hoffnung, dass
das was ändern würde (da man ja für das Ändern der Clocksource später
einen backup domain reset bräuchte).
1
if((__RTC_CLKSRC_VAL&RCC_BDCR_RTCSEL)==0x00000100){// LSE is RTC clock source
2
RCC->BDCR|=RCC_BDCR_LSEON;// enable LSE
3
while((RCC->BDCR&RCC_BDCR_LSERDY)==0);// Wait for LSERDY = 1 (LSE is ready)
4
}
5
6
if((__RTC_CLKSRC_VAL&RCC_BDCR_RTCSEL)==0x00000200){// LSI is RTC clock source
7
RCC->CSR|=RCC_CSR_LSION;// enable LSI
8
while((RCC->CSR&RCC_CSR_LSIRDY)==0);// Wait for LSERDY = 1 (LSE is ready)
9
}
10
11
RCC->BDCR|=(__RTC_CLKSRC_VAL|RCC_BDCR_RTCEN);// set RTC clock source, enable RTC clock
__RTC_CLKSRC_VAL ist bei denen entweder 0x100 für LSE oder 0x200 für
LSI.
Wenn ich ihn nach den Einzelschritten weiter laufen lasse, ist er
durchaus stabil. Der Zähler zeigt eine Periode von 1,9999289 s an
(Periodendauer der blinkenden LED), die Anzeige wackelt höchstens mal in
der letzten Stelle. Das sieht schon nach Quarz aus, nicht nach LSI oder
sowas. Die Frequenz ist 35 ppm zu niedrig, hmm. Muss ich mal gucken, ob
er noch anschwingt, wenn ich die Last-Cs kleiner mache.
Ich hatte den Fall, dass der RTC nicht immer anlief, wenn die
Onboard-LED leuchtete. Die Ströme sind extrem niedrig. Bei schlechten
Schwingkreisen reichen dann kleinste Kleinigkeiten. Kannst Du den Test
mit einen anderen STM32 wiederholen?
zum Quarz gibt es eine AN von ST, da sind die STM32 sehr
unterschiedlich. Bei den neueren Serien kann man sogar den Treiber für
verschiedene Lasten konfigurieren.
Du machst einige Registerzugriffe in einer anderen Reihenfolge als ich
und hast weniger "waits" drin. Vergleiche das mal mit meinem Beispiel:
http://stefanfrings.de/stm32/stm32f1.html#rtc
Falls du ein Blue-Pill Board verwendest, entferne die beiden Stifte an
den Pins PC14 und PC15.
Das ist kein Bluepill, sondern der Controller ist 'ne Nummer größer
(pinzahlmäßig), aber ich habe mich weitgehend an die Schaltung vom
Bluepill gehalten.
Dass der Controller sehr mimosenhaft bezüglich des 32-kHz-Quarzes ist,
ist mir schon aufgefallen: eine Serie SMD-Quarze aus der Bastelkiste,
von denen ich ein paar Dutzend habe und die mit AVRs immer klaglos
funktioniert haben, funktioniert hier gar nicht, der Quarz schwingt
nicht an. Jetzt habe ich zwei verschiedene ausgelötete benutzt und 2 x
10 pF als Last-Cs. Der eine ist ein SMD-Quader, der schafft es offenbar
nicht immer, aber meist gerade so mit dem Anschwingen. Der andere ist
ein (THT-)Stabquarz, vermutlich mal aus 'ner alten Uhr ausgeschlachtet,
der tut's besser.
Beide schwingen aber zu langsam, der Stabquarz liegt so bei -22 ppm.
Wenn ich die Last-Cs ganz weglasse, schwingen sie jedoch auch nicht.
Mit bissel Experimentieren mit dem Breakpoint im Debugger, habe ich nun
gefunden, dass diese Reihenfolge offenbar geht:
1
RTC->CRL&=~RTC_CRL_CNF;
2
3
while((RTC->CRL&RTC_CRL_RTOFF)==0){/* wait */}
4
5
PWR->CR&=~PWR_CR_DBP;
Also erst das CNF in RTC->CRL löschen, dann warten bis RTOFF gesetzt,
dann das DBP in PWR->CR zurück nehmen. Dass man DBP setzen muss, um an
den RTC-Registern etwas zu ändern, ist dokumentiert. Dass das vorzeitige
Zurücknehmen jedoch offensichtlich auch interne Schreibzugriffe (das
Setzen von RTOFF) verhindert und nicht etwa nur die von der CPU, steht
dagegen nirgends. Wäre allerdings nach all dem die logische Erklärung
dafür. Lesbar sind die RTC-Register ja auch danach immer noch.
Danke an alle für die Rückmeldungen!
Jörg W. schrieb:> Dass das vorzeitige Zurücknehmen jedoch offensichtlich> auch interne Schreibzugriffe (das Setzen von RTOFF) verhindert> und nicht etwa nur die von der CPU, steht dagegen nirgends.
Mit solchen Überraschungen geizen die STM32 alle nicht. AVR sind mir in
dieser Hinsicht deutlich angenehmer.
Jörg W. schrieb:> der Stabquarz liegt so bei -22 ppm.
Es gibt da ein Register für das Finetuning der RTC zum Ausgleichen der
Abweichung.
Bei meiner Scopeuhr hab ich das damals genutzt und es funktionierte
recht gut. Aber frag mich nicht, welches Register, ist zu lange her ;)
Jörg W. schrieb:> Software tunen
Nee, hier geht es auch in Hardware. Dafür haben sie ein Register
eingebaut, der lässt Finetung der RTC Counter zu. Da brauchst du zum
Tunen keine SW.
Da sehe ich beim STM32F103 nichts in so einer Richtung. Es gibt
prescaler load, prescaler divider, counter und alarm als Register in der
RTC.
Vielleicht haben größere STM32 da mehr Spielraum.
Aber, ich sehe gerade, Denkfehler: die Frequenz ist zu hoch. Man könnte
also mit größeren Cs noch was machen, allerdings dürfen die Cs laut
Datenblatt maximal 15 pF groß werden. Das schränkt schon ziemlich stark
ein.
900ss D. schrieb:> Hab bei mir folgendes gefunden, also über den Prescaler hab ich es> gemacht.
Naja, eine Änderung von 1 im Prescaler entspricht einer Justage von 30
ppm. Das ist schon arg grob.
So, habe nochmal Cs getauscht. Fühle mich ruhiger, wenn der Quarz nahe
am Sollwert ist, denn dann ist die Chance gut, dass er die korrekte Last
sieht. Das eine Board ist mit dem Maximum von 2 x 15 pF immer noch bei
+14 ppm, das andere (mit dem Stab-Quarz) ist mit 15/12 pF bei +3 ppm.
Jörg W. schrieb:> Nur seltsam, warum das Dingens in BKP sitzt und nicht in RTC.
Beim STM32F103 ist einiges seltsam. Man merkt dass es der erste
"Versuch" dieses Herstellers war. Der STM32F303 ist schon deutlich
logischer aufgebaut.
Jörg W. schrieb:> Fühle mich ruhiger, wenn der Quarz nahe> am Sollwert ist, denn dann ist die Chance gut, dass er die korrekte Last> sieht.
Wenn du einen hochohmigen Tastkopf hast, könntest du den Pegel ja live
überprüfen und auch zuschauen, wie er anschwingt.
Matthias S. schrieb:> Wenn du einen hochohmigen Tastkopf hast, könntest du den Pegel ja live> überprüfen und auch zuschauen, wie er anschwingt.
Habe ich, aber den erst auszubuddeln, war ich zu faul. ;-)
Jörg W. schrieb:> So, habe nochmal Cs getauscht. Fühle mich ruhiger, wenn der Quarz nahe> am Sollwert ist, denn dann ist die Chance gut, dass er die korrekte Last> sieht
Jörsch,
frickel nicht so viel da herum.... ich habe die Pillen seit Frühjahr im
Auto vorne am Laufen beim GPS Logger. So ab ca 30 Grad Temperatur laufen
die Quarze gar nicht mehr an. Und bei jedem gefühlt 100.ten Einschalten
auch nicht.
Das ist eben so..... lieber einen Quarzoscillator nehmen wenn es drauf
ankommt. Ist bei meinem GPS aber wumpe, die Uhrzeit kommt aus dem SAT
und wird jeden Tag neu gestellt.
Das gehörte noch zum sportlichen Ehrgeiz. ;-)
Habe bei der Gelegenheit mal wieder üben dürfen, wie ich mit dem alten
Ч3-54 Periodendauern messe. Vielleicht kann ich mir's ja merken, bis ich
die Funktion das nächste Mal benötige …