fbpx

Zegar czasu rzeczywistego w mikrokontrolerach STM32 nie jest taki sam we wszystkich rodzinach. W zasadzie możemy spotkać dwa różne RTC. Jeden podstawowy, który znajduje się w starszych i mniej zaawansowanych mikrokontrolerach jak w serii F1, którym zająłem się nim w poprzednich artykułach. Jest jeszcze bardziej zaawansowany zegar, który możesz znaleźć, chociażby w rodzinie F4 i temu właśnie się tym razem przyjrzę.

RTC w STM32F4

Jak już wspomniałem w ST32F4 układ RTC jest bardziej zaawansowany. W F1 mieliśmy tylko jeden licznik 32-bitowy, który był w stanie zliczać pojedyncze sekundy bez rozróżnienia innych składowych daty czy czasu. To od programisty zależało, w jaki sposób wykorzysta te sekundy do złożenia daty i godziny.

W F4 natomiast zegar został wyposażony w dodatkowe liczniki, które są podzielone na mniejsze kawałki, które oznaczają już konkretnie godzinę, minutę czy sekundę.

Dodatkowo dodano osobny licznik, który ma za zadanie dbać o zliczanie daty. Można by powiedzieć, że ta najtrudniejsza część biblioteki została z nas zdjęta, co nie? Ostatnio przy F1 nieco musiałem się namęczyć, aby data poprawnie chodziła po podtrzymaniu zasilania… Zobaczymy jak będzie tutaj 🙂

Jednak to nie wszystkie dodatki, które są w RTC dla F4. Zobacz na porównanie ilości rejestrów z Reference Manuali STM32F103C8T6 i STM32F401CCU6.

Lista jest o wiele dłuższa! Można by rzec, że RTC stał się jednocześnie bardziej skomplikowany w obsłudze, bo chociazby procedury wpisywania do rejestrów są nieco bardziej wymagające w F4 w porównaniu do F1. Na szczęście HAL nam pozwala nie martwić się zbytnio tymi procedurami.

Dodatkowe funkcje RTC

Z dodatków, które doszły do RTC można zauważyć chociażby drugi alarm. Teraz są dwa – A i B. Swoją drogą napisz w komentarzu, w jaki sposób ciekawy można użyć alarmu? Najlepiej coś nieoczywistego 🙂

Fajnym ficzerem, który znajdziesz w zaawansowanym RTC są rejestry związane z “subsekundami”. Czym jest ta tajemna “subsekunda”? Znamy, chociażby milisekundy, którymi możemy się posługiwać w elektronice, ale jakieś sub??

Te subsekundy to również części sekund, ale sekunda dzielona jest nieco inaczej. Mamy możliwość ustawienia na ile części ma się dzielić sekunda. Jest jeszcze możliwość ustawienia preskalrea RTC jednak uważaj bo grzebiąc przy tych rejestrach możesz łatwo rozjechać sekundę. Domyślne ustawienia działają dobrze. Później pokażę Ci jak wyłuskać z tych liczb milisekundy.

Warto zwrócić uwagę na rejestry związane z funkcją Wake Up. Pozwala ona na wybudzenie mikrokontrolera z trybów obniżonego poboru energii. Bardzo przydatna rzecz, zwłaszcza w mikrokontrolerach serii L, których używamy właśnie do energooszczędnych aplikacji.

Jest też coś takiego jak Time Stamp. Można zatrzasnąć datę i godzinę na podstawie zbocza na specjalnym pinie. Zatrzaskiwanie działa w różnych trybach low-powerowych. Można to połączyć z funkcją Tamper, czyli czyszczeniem rejestrów backupowych po “włamaniu”.

Nie zabrakło oczywiście rejestrów backupowych, a także mamy do dyspozycji kilka dodatkowych rejestrów kalibracyjnych.

Platforma testowa

stm32f411

Poprzednio używałem BluePill, więc teraz wezmę coś podobnego. Jest to niejako jego następna zwany BlackPill. Opisywałem niedawno te płytki. Wziąłem wersję z STM32F401CC.

Oprogramowanie, którego użyję to:

  • STM32CubeIDE v1.2.0
  • STM32CubeMX v5.5.0 wbudowany w IDE
  • HAL F4 v1.24.2

Konfiguracja w CubeMX

Do celów testowych, oprócz RTC potrzebuję jeszcze kilku innych rzeczy.

Najpierw zegary:

  • HCLK ustawiłem na maksymalną wartość 84 MHz korzystając z wewnętrznego oscylatora HSI.
  • Jako zegar dla RTC na początek wziąłem LSI. Oczywiście sprawdzę też działanie na LSE.

Do celów debugowych użyłem:

  • UART2 w konfiguracji 115200 8n1
  • Serial Wire w zakładce System Core > SYS > Debug > Serial Wire
  • Wejście GPIO PA10 oznaczone jako TEST do ręcznego ustawiania daty i czasu.

Teraz można ze spokojem ustawić RTC w zakładce Timers.

Konfiguracja jest podobna do tej z F1. Zaznacz ptaszek Activate Clock Source, aby podać taktownie i włączyć RTC.

Dodatkowo aktywuj kalendarz. Tym razem nie będzie to dołączenie programowego kalendarza z biblioteki jak poprzednio, a użycie sprzętowego dostarczanego przez RTC.

Ustaw sobie datę i godzinę, jaką chcesz. W STM32F4 masz też informację o tym, czy jest to czas letni, czy zimowy. Rok zapisujesz w zakresie 0-99.

Tak skonfigurowany projekt możesz wygenerować.

Kod RTC

W projekcie dostaliśmy wygenerowaną bibliotekę do użycia RTC. Podobnie jak poprzednio znajdują się w niej struktury odpowiadające za trzymanie czasu i daty.

Dodano do nich zmienne odpowiadające dodatkowym funkcjom jak format czasu(12/24H) czy czas letni/zimowy. Jest tutaj też informacja o subsekundach i to na jej podstawie będziemy obliczać milisekundy.

Czytanie danych z RTC wygląda dosłownie tak samo jakw przypadku F1.

ALE jest tu jeden warunek. MUSISZ zawsze odczytać najpierw czas, a później datę. Nawet jest to napisane w komentarzu do tych funkcji.

Związane jest to z tak zwanymi shadow registers. W momencie rozpoczęcia odczytu czasu dane są zatrzaskiwane po to, aby zachować spójność danych i poprawność odczytu. W trakcie czytania RTC dalej zlicza właśnie w tych ukrytych rejestrach, natomiast te dostępne dla użytkownika są zatrzaśnięte.

Musisz odczytać wszystko, aby rejestry znów się odblokowały. Wiem, że to sprawia mnóstwo problemów początkującym 🙂

Podmiana daty na starcie

Tutaj niestety też jest ten problem w bibliotece i rozwiązujemy go podobnie jak w bibliotece do STM32F1 poprzez return w sekcji odzysku z rejestrów backupowych.

Przy okazji startu możemy odczytać to, co znajduje się w RTC.

I to tyle! Na prawdę. Patrząc na moje poprzednie męki z biblioteką ST aż ciężko jest w to uwierzyć. Jednak dla F4 biblioteka jest lepiej napisana. Śmiem twierdzić, że najpierw napisano tę dla F4, a później bardziej lub mniej bezmyślnie ją przeportowano na F1.

Zasilanie bateryjne BlackPill

Pamiętasz dziwne zachowanie BluePilla, które polegało na tym, że podpinając baterię do VBAT, RTC nadal nie chodził bez zasilania MCU?

Problem polegał na braku kondensatora przy pinie VBAT. Dodanie 100 nF załatwiło sprawę. Jak jest w BlackPill? Tutaj według schematu jest taki kondensator położony. Jednak nie wiadomo jaką on ma wartość. Sprawdzę jednak, czy działa.

I… to działa. RTC chodzi pod samą baterią. Spora przewaga BlackPilla nad BluePill, jeśli zaczynasz z programowaniem i praktycznie nie masz szans na wyłapanie takiego błędu samemu.

Zewnętrzny rezonator LSE

Z BluePillem był jeszcze jeden problem. Tym razem związany z rezonatorem zewnętrznym dla RTC. Błąd polegał na jednoczesnym wyprowadzeniu pinów od oscylatora na goldpiny, co powodowało fluktuacje częstotliwości i niepoprawne zliczanie czasu. Jak jest w BlackPill? Również zerknę na schemat.

Niestety tutaj popełniono ten sam błąd. Jeśli chciałbyś skorzystać z położonego na płytce oscylatora, musisz usunąć goldpiny dla PC14 i PC15 bo inaczej RTC będzie źle zliczał.

Milisekundy

Wspomniałem na początku, że jesteśmy w stanie wyciągnąć ze wbudowanego RTC w F4 milisekundy. Mogą się przydać, chociażby do printowania logów z działania mikrokontrolera.

Do policzenia milisekund wykorzystam zmienne SubSeconds oraz SecondFraction, które znajdują się w strukturze przechowującej czas. Dane te pobierane są z rejestrów RTC.

W opisie do funkcji pobierania czasu mamy taką notkę.

Jest w niej podany wzór, z którego trzeba skorzystać. Wynik, jaki otrzymasz wyrażony jest w setnych częściach sekundy np. 0,67 s. Nie chciałbym przechowywać liczby milisekund w zmiennym przecinku, więc pomnożę wynik razy 100. Jednak to nadal nie będzie działać, bo i tak trzeba będzie wykonać po drodze dzielenie na float.

Ostatecznie kod liczący liczbę milisekund wygląda tak.

Teraz można wyprintować milisekundy. Działa to dosyć fajnie 🙂

Podsumowanie

Z pracą na RTC w STM32F4 mam o wiele lepsze doświadczenia niż na F1. Głównie za sprawą lepiej działającej biblioteki od ST, którą można z powodzeniem używać od ręki. A Ty jaką masz opinię?

W kolejnym artykule sprawdzimy te dodatkowe funkcje w RTC. Pokażę Ci jak je ustawić i jak działają takie rzeczy jak Alarm, WakeUp czy Time Stamp.

Pełny projekt wraz z biblioteką znajdziesz jak zwykle na moim GitHubie: LINK

Jeśli zauważyłeś jakiś błąd, nie zgadzasz się z czymś, chciałbyś coś dodać istotnego lub po prostu uważasz, że chciałbyś podyskutować na ten temat, napisz komentarz. Pamiętaj, że dyskusja ma być kulturalna i zgodna z zasadami języka polskiego.


Raz na jakiś czas wyślę Ci też e-mail z ciekawymi rzeczami które znalazłem


2 Komentarze

Piotrek · 13/05/2020 o 18:28

Super opisane, dużo zrozumiałem, jednak mam jeden problem, dlaczego jak w cubie aktywuje przerwanie od RTC i włączę internal wakeup po wejściu w sleep od razu jestem budzony? Żeby wejść w sleepa daje:
HAL_SuspendTick();
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);

    Mateusz Salamon · 18/05/2020 o 13:56

    Pewnie masz jeszcze jakieś inne przerwanie 🙂

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *