Hallo zusammen, Ich habe heute endlich mal Zeit gefunden mich mit dem STM32 auseinanderzusetzen. Leider ist das mehr oder weniger eine gezwungene Massnahme, da Arduino leider langsam an der Grenze ist bei mir. Informationen zur Programmierung STM32 sind oft schwerer zu finden als für Arduino :( (Für Arduino findet man für fast alles eines oder mehrer Codebeispiele sogar auf der Haupseite. Bei STM32 habe ich bis jetz noch keine Codeexamples zu Funktionen endeteckt) Ich habe mich nun mit der CooCoxIDE und dem Nucleo STM32F401RE versucht Die LED blinken lassen funktioniert :-) Da für meine zwecke die RTC von zentraler Bedeutung ist, wollte ich mich daran versuchen. Nun habe ich zwei Probleme: 1.) Die meisten Tutorials benutzen die "Standart Peripheral Libary" nich die HAL. In der Aktuellen Version von CooCox ist aber ist diese nicht mehr vorhanden und auch das GUI sieht anders aus als bei den Meisten Tutorials. Es scheint so als kommt neu immer das Paket "STM32_TYP_Cubelib" zum Einsatz welche auf der HAL Library basiert. Kann man die Standard-Lib nachinstallieren oder ist es sinnvoller diese nicht mehr zu benutzen? 2.) Kennt jemand hier ein funktionierendes Beispiel mit HAL wie man die RTC in Betrieb nimmt, die Zeit setzt und wieder die Zeit liest? Ich habe bereits eine Library gefunden, jedoch zweifle ich an deren Zweck, da ja in der STM32_HAL_rtc schon befele für "GetDate" vorhanden sind.. ebenfalls verhindern Libaries immer das Wissen, denn wenn man eine Libary einsetzt weiss man trotzdem nicht was da passiert und wenn die library mal nicht mehr geht oder end of life ist sitzt man im Sumpf. Für gewisse komplexe Sachen machen libaries auch sinn, aber ich denke mal die RTC sollte auch so mit mässigem Aufwand betreibbar sein? Vielen Dank für eure Antworten
Welcher STM32 ist es denn? Die STM32Fx HAL (x=1,2,3,4) findet man im Internet als Zusatzdownload zum CubeMX (CubeMX braucht man nicht). Bei dem Download der HAL sind dann auch Beispiele dabei - auch für die RTC. Konkrete Hilfe / Code Snippets wirst du erst bekommen, wenn du sagst, welchen STM32 du einsetzt, die verhalten sich nämlich z.T. unterschiedlich. Das Benutzen der HAL ist für dich i.O. oder ist das auch schon "zuviel" Bibliothek? Grüße Lasse
Johnny S. schrieb: > Da für meine zwecke die RTC von zentraler Bedeutung ist, wollte ich mich > daran versuchen. Hast mal nachgeschaut ob da der 32768Hz Quarz überhaupt bestückt ist? IIRC war das nicht bei allen Versionen der Fall, aber ich kann mich da auch irren. Ohne den Quarz wird aus der RTC ein Schätzeisen...
Ah, jetzt hab sogar ich's gesehen, STM32F401. Schau da einfach mal in den Download der HAL, da sollte ein RTC-Beispiel sein. Für den STM32F303 nutze ich folgenden Code:
1 | {
|
2 | // lse config
|
3 | __HAL_RCC_PWR_CLK_ENABLE(); |
4 | HAL_PWR_EnableBkUpAccess(); |
5 | __HAL_RCC_BACKUPRESET_FORCE(); |
6 | __HAL_RCC_BACKUPRESET_RELEASE(); |
7 | HAL_PWR_DisableBkUpAccess(); |
8 | |
9 | RCC_OscInitTypeDef lseinit; |
10 | lseinit.OscillatorType = RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI; |
11 | lseinit.PLL.PLLState = RCC_PLL_NONE; |
12 | lseinit.LSEState = RCC_LSE_ON; |
13 | lseinit.LSIState = RCC_LSI_OFF; |
14 | HAL_StatusTypeDef lsestatus = HAL_RCC_OscConfig(&lseinit); |
15 | }
|
16 | |
17 | {
|
18 | RTC_DateTypeDef dateinit; |
19 | RTC_TimeTypeDef timeinit; |
20 | |
21 | // TODO: Check RTC settings, these are simply copypasted from example
|
22 | __HAL_RCC_PWR_CLK_ENABLE(); |
23 | HAL_PWR_EnableBkUpAccess(); |
24 | __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE); // TODO: change clock source to a low power mode |
25 | __HAL_RCC_RTC_ENABLE(); |
26 | |
27 | // initialize rtc
|
28 | rtc.Instance = RTC; |
29 | rtc.Init.HourFormat = RTC_HOURFORMAT_24; |
30 | rtc.Init.AsynchPrediv = 0x7F; |
31 | rtc.Init.SynchPrediv = 0x00FF; |
32 | rtc.Init.OutPut = RTC_OUTPUT_DISABLE; |
33 | rtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; |
34 | rtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; |
35 | HAL_StatusTypeDef init = HAL_RTC_Init(&rtc); |
Ist sicherlich noch optimierbar, läuft so aber - bei mir.
Lasse S. schrieb: > Welcher STM32 ist es denn? STM32F401RE, hatte ich bereits oben genannt :) Jim M. schrieb: > Johnny S. schrieb: >> Da für meine zwecke die RTC von zentraler Bedeutung ist, wollte ich mich >> daran versuchen. > > Hast mal nachgeschaut ob da der 32768Hz Quarz überhaupt bestückt ist? > IIRC war das nicht bei allen Versionen der Fall, aber ich kann mich da > auch irren. > > Ohne den Quarz wird aus der RTC ein Schätzeisen... Der Quarz fehlt, jedoch ist meinem Verständins nach dieser nur von nötigkeit wenn man den STM32 in Batteriebetrieb auf Low-Power benutzen möchte. Man kann auch einstellen das die RTC vom normalen Quarz versorgt wird. Klar, bei jedem Power-Off ist die RTC dann null. In Arduino gibt es die Bibliotek "Time.h", welche eine Art virtuelle RTC ist. Es geht mir Hauptsächlich darum beim Start eine Zeit zu setzen, und diese soll dann selbständig laufen (mit Datumswechsel etc), so dass ich wenn nötig mit "GetDate / GetTime" den Wert beziehen kann.
> Man kann auch einstellen das die RTC vom normalen Quarz versorgt wird.
Mag sein, aber dann ist es keine richtige RTC, denn der normale HSE
Ozillator erreicht normalerweise kaum die Genauigkeit des LSE. Wenn du
den HSE verwendest, kannst du gleich den Systick Timer anstatt der
Echtzeituhr benutzen.
Stefan U. schrieb: >> Man kann auch einstellen das die RTC vom normalen Quarz versorgt wird. > > Mag sein, aber dann ist es keine richtige RTC, denn der normale HSE > Ozillator erreicht normalerweise kaum die Genauigkeit des LSE. Wenn du > den HSE verwendest, kannst du gleich den Systick Timer anstatt der > Echtzeituhr benutzen. Da hast du recht, mir geht es aber auch nicht um 100% genaue Zeitmessung. Ich möchte von Arduino auf STM32 umsteigen. Aktuell benutze ich die Library "time.h" auf Arduino. Da der ATmega328 garkeine Hardware-RTC hat muss die "Zeitspeicherung" also immer in Software passieren. Es ist halt schöner "getDate()" abzurufen als jedes mal zu rechnen... Klar könnte ich jeweils beim STM32 mit einem Systick jede Sekunde zählen und dann auf Stunden&Tage umrechnen, aber warum mehr aufwand wenn die RTC das selbe bietet? Die Endanwendung ist dann wie folgt: - Programmstart - Zeit aus RTC (DS3231) per I2C in die STM RTC Laden - Falls vorhanden Zeit aus GPS / NTP beziehen, RTC updaten - Programmlauf... - Stündliche Kontrolle der Zeit per I2C mit DS3231 oder GPS/NTP. (Update der internen RTC falls nötig) Da GPS und NTP jeweils GMT+0 liefern, speichere ich nur die GMT+0 in der DS3231 und benutze dann jeweils Code um die Zeitzone anzupassen, anstatt beim Zeitzonenwechsel jeweils wirklich die Zeit in der RTC anzupassen.
:
Bearbeitet durch User
Vergiss nicht, Sommer-/Winterzeit Umschaltung und Schaltjahre zu berücksichtigen. Das kann nicht jede RTC, ohne Softwareunterstützung. > Zeit aus RTC (DS3231) per I2C in die STM RTC Laden Warum macht man das? Schließe doch einfach einen Quarz und eine Batterie an den STM32 an.
Stefan U. schrieb: > Vergiss nicht, Sommer-/Winterzeit Umschaltung und Schaltjahre zu > berücksichtigen. Das kann nicht jede RTC, ohne Softwareunterstützung. Ja, nur haben nicht alle Zeitzonen Sommer/Winterzeit somit ist es ratsam die Zeit in "neutral" zu speichern. Aktuell lese ich beim start alle Benutzereinstellungen aus einem EEprom, dort steht auch die Zeitzone und Sommerzeit JA/NEIN >> Zeit aus RTC (DS3231) per I2C in die STM RTC Laden > > Warum macht man das? Schließe doch einfach einen Quarz und eine Batterie > an den STM32 an. Man macht es für hohe Genauigkeit. Ein STM32 welcher um die 5€ kostet und Hauptsächlich ein uC ist, wird mitnichten so genau sein wie ein DS3231 Baustein für um 10€. Der DS3231 hat +-2ppm. Klar, die hohe Genauigkeit spielt nur dann eine Rolle wenn weder GPS noch NTP zur "dauersynchronisation" vorhanden sind, aber ich möchte gerne weiterhin die Möglichkeit bieten.
Ich bin nun mal so weit:
1 | HAL_Init(); |
2 | |
3 | /* Configure the system clock to 84 MHz */ |
4 | SystemClock_Config(); |
5 | |
6 | /* -1- Enable GPIOA Clock (to be able to program the configuration registers) */ |
7 | __HAL_RCC_GPIOA_CLK_ENABLE(); |
8 | __HAL_RCC_PWR_CLK_ENABLE(); |
9 | __HAL_RCC_RTC_ENABLE(); |
10 | |
11 | rtc.Instance = RTC; |
12 | rtc.Init.HourFormat = RTC_HOURFORMAT_24; |
13 | rtc.Init.AsynchPrediv = 0x7F; |
14 | rtc.Init.SynchPrediv = 0x00FF; |
15 | rtc.Init.OutPut = RTC_OUTPUT_DISABLE; |
16 | rtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; |
17 | rtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; |
18 | |
19 | if(HAL_RTC_Init(&rtc) != HAL_OK) |
20 | { |
21 | /* Initialization Error */ |
22 | Error_Handler(); |
23 | } |
24 | |
25 | sdatestructure.Year = 0x14; |
26 | sdatestructure.Month = RTC_MONTH_FEBRUARY; |
27 | sdatestructure.Date = 0x18; |
28 | sdatestructure.WeekDay = RTC_WEEKDAY_TUESDAY; |
29 | |
30 | if(HAL_RTC_SetDate(&rtc,&sdatestructure,RTC_FORMAT_BCD) != HAL_OK) |
31 | { |
32 | /* Initialization Error */ |
33 | Error_Handler(); |
34 | } |
35 | stimestructure.Hours = 0x02; |
36 | stimestructure.Minutes = 0x20; |
37 | stimestructure.Seconds = 0x00; |
38 | stimestructure.TimeFormat = RTC_HOURFORMAT12_AM; |
39 | stimestructure.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; |
40 | stimestructure.StoreOperation = RTC_STOREOPERATION_RESET; |
41 | |
42 | if(HAL_RTC_SetTime(&rtc,&stimestructure,RTC_FORMAT_BCD) != HAL_OK) |
43 | { |
44 | /* Initialization Error */ |
45 | Error_Handler(); |
46 | } |
Aber der Debugger zeigt mir das der Error_Handler(); schon beim INIT anspricht... Wo mache ich denn den Fehler?
:
Bearbeitet durch User
Mit dem fehlschlagenden Init meinst du das HAL_RTC_Init, oder? Hast du den Clocksource für die RTC eingestellt, ich weiß nicht, ob der Default so funktioniert.
> wie wäre es mit OpenSTM32 IDE
Der Vorschlag ist nett aber ich denke er löst das Problem nicht.
Clock-Source wäre auch mein Vorschlag.
Sooo.. die Errors sind schonmal weg. Es war ein grundsätzlcihes Problem Das Nucleo-board hat zwar einen Quarz, aber dieser ist eben genauf für die RTC nicht für den Prozessor selber :-) Der interne Takt wird vom "HSI" produziert. Da kann man lange auf den nicht vohandenen HSE intialisieren. Mit dem LSI (QUarz) läuft nun die RTC bzw. zumindestens die Init schlägt nicht fehl, mal sehen wie es nun weiter geht.
Nächstes Problem
1 | while (1) |
2 | { |
3 | HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); |
4 | /* Insert delay 100 ms */ |
5 | HAL_RTC_GetTime(&rtc,&stimestructure,FORMAT_BIN); |
6 | int test = stimestructure.Seconds; |
7 | HAL_Delay(10000); |
8 | } |
&stimestructure enthält die Zeitelemente gemäss Screenshot. Ich habe beim init 00:00:01 gesetzt. Leider bleibt die Zeit so stehen. Die RTC scheint aber zu laufen, da SubSeconds sich verändert.
Probier mal, die Zeit aus den RTC-Registern selber auszulesen, das GetTime aus der HAL hat bei mir auch Probleme gemacht.
1 | uint32_t tmpreg = rtc.Instance->TR; |
2 | |
3 | uint8_t ht = (tmpreg & RTC_TR_HT) >> RTC_TR_HT_Pos; |
4 | uint8_t hu = (tmpreg & RTC_TR_HU) >> RTC_TR_HU_Pos; |
5 | uint8_t hours = ht*10 + hu; |
6 | |
7 | uint8_t mt = (tmpreg & RTC_TR_MNT) >> RTC_TR_MNT_Pos; |
8 | uint8_t mu = (tmpreg & RTC_TR_MNU) >> RTC_TR_MNU_Pos; |
9 | uint8_t minutes = mt*10 + mu; |
10 | |
11 | uint8_t st = (tmpreg & RTC_TR_ST) >> RTC_TR_ST_Pos; |
12 | uint8_t su = (tmpreg & RTC_TR_SU) >> RTC_TR_SU_Pos; |
13 | uint8_t seconds = st*10 + su; |
Ich weiß nicht ob das auf den STM32F4 auch so passt, aber ich musste beim STM32F1 noch einen Teilerfaktor einstellen:
1 | // Enter configuration mode
|
2 | SET_BIT(RTC->CRL,RTC_CRL_CNF); |
3 | |
4 | // Divide oscillator frequency by 32767+1 to get seconds
|
5 | RTC->PRLL=32767; |
6 | RTC->PRLH=0; |
7 | |
8 | // Leave configuration mode
|
9 | CLEAR_BIT(RTC->CRL,RTC_CRL_CNF); |
10 | |
11 | // Wait until last write operation is done
|
12 | while(!READ_BIT(RTC->CRL, RTC_CRL_RTOFF)) {} |
Soweit ich verstanden habe, liegt dieser Teiler zwischen dem Oszillator und dem Sekundenzähler. Das müsste deinen "SubSeconds" entsprechen. Deswegen tippe ich auf den Teilerfaktor.
Alternativ musst du nach dem Aufruf von HAL_RTC_GetTime zwingend auch HAL_RTC_GetDate aufrufen (siehe Doku in der HAL).
Ich sehe gerade, dass der Teilerfaktor offensichtlich bereits durch
1 | rtc.Init.AsynchPrediv = 0x7F; |
2 | rtc.Init.SynchPrediv = 0x00FF; |
eingestellt wurde.
Lasse S. schrieb: > Probier mal, die Zeit aus den RTC-Registern selber auszulesen, das > GetTime aus der HAL hat bei mir auch Probleme gemacht. Zeigt leider selbes Ergebnis
pegel schrieb: > Lasse S. schrieb: >> nach dem Aufruf von HAL_RTC_GetTime zwingend auch >> HAL_RTC_GetDate aufrufen So ein Quark :( Naja, jetz läufts...
Ich hatte nicht HAL_RTC_GetDate nach HAL_RTC_GetTime aufgerufen... scheinbar muss dass immer zusammen abgerufen werden.
Na gut zu wissen. Darauf wäre ich nie gekommen. Sollte die HAL solche Details nicht eigentlich vereinfachen bzw. weg abstrahieren? Je länger ich mit STM32 zu tun habe umso sinnloser erscheint mir die HAL. Nicht dass ich Arduino toll fände, aber das können die Arduino Macher besser.
Was ihr nur immer gegen HAL habt. Ich finde es gut und es funktioniert einfach. Ich gehe wie folgt vor: - in CubeMX Takt und Peripherie einstellen - in SW4STM32 importieren - für die gewünschte Hardware in die Beispiele schauen - anpassen und ergänzen - fertig Beim RTC Beispiel ist neben dem korrekten Setzen und Lesen des RTC auch noch eine Erkennung ob die Uhr beim Reset schon gestellt ist dabei.
> anpassen und ergänzen, fertig
Offensichtlich weicht da die Theorie ein wenig von der Praxis ab.
Mein erster Versuch scheiterte schon an der Initialisierung des
Taktgebers. nach stundenlangem Suchen bekam ich mit freundlicher Hilfe
dieses Forums heraus, dass es sich um einen Bug handelte.
Seit dem lese ich das Referenzhandbuch, wodurch die HAL für mich
überflüssig geworden ist.
> War das das HSI HSE Problem in Version 4.20?
Keine Ahnung ob das mein Problem "das" eine war.
pegel schrieb: > Beim RTC Beispiel ist neben dem korrekten Setzen und Lesen des RTC auch > noch eine Erkennung ob die Uhr beim Reset schon gestellt ist dabei. Sind das beispiele von ST? Falls ja, kannst du mir bitte die Quelle nennen, ich suche seit ewigkeiten nach code Beispielen :/
aktuell für dein Board: STM32Cube_FW_F4_V1.18.0/Projects/STM32F401RE-Nucleo Aber dank HAL, lassen sich auch Beispiele von anderen Familien übernehmen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.