STM32 - CooCox Fragen & RTC

OP #5255657
Lesenswert?

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
Persönliche Seite #5255663
Lesenswert?

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
Persönliche Seite #5255668
Lesenswert?

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.
OP #5255671
Lesenswert?

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.
Gast #5255706
Lesenswert?

> 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.
OP #5255785
Lesenswert?

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.
Gast #5255795
Lesenswert?

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.
OP #5255835
Lesenswert?

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.
OP #5255871
Lesenswert?

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?
OP #5256298
Lesenswert?

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.
OP #5256346
Lesenswert?

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.
Angehängte Dateien:
Persönliche Seite #5256368
Lesenswert?

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;
Gast #5256374
Lesenswert?

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.
Gast #5256627
Lesenswert?

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.
Gast #5256708
Lesenswert?

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.
Gast #5256826
Lesenswert?

> 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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren