fbpx

Ostatnio swoją uwagę skupiłem na niesamowicie dokładnym RTC DS3231. Nie wymagał on zewnętrznego kwarcu oraz posiada dodatkowo wbudowaną kompensację temperaturową. Jednak na rynku istnieje mnóstwo innych zegarów czasu rzeczywistego. Jednak niekoniecznie chwalą się tym, że są dokładne. Zerknijmy bliżej co one oferują i jak się z nimi obchodzić.

DS1307

DS1307 jest jednym z najpopularniejszych RTC. Najczęściej to on jako pierwszy wyskakuje w wyszukiwarkach. Został też opisany na wszystkie możliwe sposoby. Istnieje mnóstwo gotowych modułów z tymże układem. Jeden z takich modułów możesz kupić u mnie w sklepie.

Jego sukces niewątpliwie tkwi w jego cenie. Jest on szalenie tanim scalakiem. Mimo że wymaga on dodatkowych kilku elementów zewnętrznych, to nadal się to opłaca finansowo.

Dodatkowo używanie DS1307 jest bardzo proste, o czym za chwilę.

Najpierw chciałem Ci pokazać czym się różni od omawianego w poprzednim wpisie DS3231. Pierwsze co rzuca się w oczy to napięcie zasilania. Niestety DS1307 toleruje jedynie okolice 5 V. Chcąc go używać z STM32 trzeba mieć dwa napięcia (oczywiście na Nucleo są obydwa). Na szczęście STM32 toleruje 5V na wejściach więc nie ma co się przejmować z jego strony. I2C jest na szczęście open-drain, więc nie ma problemu z translacją 3,3 -> 5 V dla DS1307.

Kolejnym ograniczeniem względem dokładnego DS3231 jest prędkość interfejsu I²C. Na DS1307 gwarantowaną stabilność uzyskasz maksymalnie dla zegara 100 kHz. Smuteczek 🙁

Dodatkowo nie ma możliwości zmiany adresu I²C. Jest jeden na stałe. Dokładnie taki sam jak ma DS3231.

Brakuje też funkcji alarmu, ale ja za tym nie płaczę. Nigdy jej nie używałem. Być może kiedyś w końcu będę tego potrzebował.

No dobra, ale czy jest coś na plus? Ano jest 🙂 DS1307 posiada 56 bajtów pamięci RAM podtrzymywanej z baterii. Bardzo fajny ficzer, gdy masz potrzebę zapamiętania jakichś danych podczas wprowadzania mikrokontrolera w najmocniejsze tryby oszczędzania energii.

Podłączenie i oprogramowanie DS1307

Dzisiaj tak samo, jak w wypadku DS3231 skorzystałem z Nucleo F410RB. Podłączenie jest zupełnie proste tak, jak w wypadku poprzedniego wpisu.

Do oprogarmowania użyłem STM32CubeIDE w wersji 1.0.2 oraz biblioteki HAL F4 w wersji 1.24.1.

Identycznie jak w wypadku poprzedniego wpisu, napisałem nieblokującą obsługę po DMA. Kody są zaskakująco bardzo podobne, ponieważ rejestry trzymające datę i czas w niemal każdym RTC wyglądają tak samo lub podobnie. Ciekawe jak czasy transferów I²C.

Pominę kwestie konfiguracji Cube’a ponieważ jest taka sama jak dla DS3231 – I²C z DMA, przerwanie EXTI dla przerwania na pojedynczym zboczu oraz UART dla printowania na terminal.

Pamiętaj jednak, że DS1307 toleruje maksymalnie 100 kHz na zegarze I²C, więc taki też ustaw.

Kod DS1307

Chciałbym się jedynie skupić na różnicach względem DS3231. Podczas inicjalizacji wymagane jest włączenie zegara taktującego układ, ponieważ po podłączeniu do zasilania RTC nie zacznie sam zliczać. Jest to ciekawy zabieg kontrolowanego startu zegara. Można też fajnie użyć tego do zliczania roboczogodzin w urządzeniu. Dodatkowo ustawiam pin SQW jako sygnał prostokątny o częstotliwości 1 Hz, aby przerwanie działało zgodnie z oczekiwaniem.

void DS1307_Init(I2C_HandleTypeDef *hi2c)
{
	hi2c_ds1307 = hi2c;

	DS1307_SQWRateSelect(SQW_RATE_1HZ);
	DS1307_SQWEnable(1);
	DS1307_ClockHalt(0);
}

Musisz pamiętać o tym, aby nadpisać funkcje callbackowe dla DMA oraz przerwania EXTI. Możesz to zrobić w czwartej sekcji kodu użytkownika w pliku main.c

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == DS1307_INT_Pin)
	{
		DS1307_ReceiveDateTimeDMA();
	}
}

void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
	DS1307_CalculateDateTime(&r);
}

I to tyle z obsługi biblioteki. Proste i przyjemne jak zawsze 🙂

Dodatkiem, o którym wcześniej wspomniałem jest pamięć RAM podtrzymywana baterią. Napisałem proste funkcje piszące do tej pamięci.

void DS1307_ReadRAM(uint8_t Address, uint8_t *Value, uint8_t Length);
void DS1307_WriteRAM(uint8_t Address, uint8_t *Value, uint8_t Length);

Zakres adresów RAM, z których możesz korzystać to 0x08 ÷ 0x3F.

Prędkość działania DS1307

Sprawdźmy jak to się zachowuje zarówno w blokującym przerwaniu, jak i po DMA.

100 kHz przerwanie

100 kHz DMA

Czas obsługi to 916 µs w przerwaniu VS 301 µs po DMA.

PCF8563

Innym popularnym układem jest PCF8563. Do niego również są moduły, które możesz nabyć w moim sklepie.

Czym wyróżnia się ten układ? Może być on niesamowicie nisko zasilany. Dla poprawnej komunikacji I²C wystarczy mu już 1,8 V. Ta wartość pozwala na użycie tego RTC w układach nastawionych na ekstremalnie niski pobór prądu.

Dodatkowo układ z chęcią przyjmie 400 kHz na zegarze I²C.

Moduł ma funkcje alarmu oraz ciekawą funkcję Timera 8-bitowego zliczającego w dół. Po zliczeniu może wystawić przerwanie. Ciekawy bajer dla tych, którym mało timerów w mikrokontrolerze.

Podłączenie i oprogramowanie PCF8563

Podłączenie jest analogiczne jak powyżej.

Konfiguracja Cube? Bez zmian 🙂 No dobra będzie jedna. PCF8563 pozwala na pracę z 400 kHz na linii zegarowej I²C, więc skorzystaj z tego, jeżeli masz 100 kHz.

Kod PCF8563

Całkiem możliwe, że już się domyśliłeś jak będzie wyglądał. Oczywiście jest podobny do poprzednich kodów. Nie implementowałem obsługi alarmu i wbudowanego Timera. Jeżeli masz ochotę, będzie mi miło, gdy zakontrybuujesz do mojego repozytorium.

Z punktu użytkowego oczywiście wystarczy zainicjować RTC oraz odczytać dane w przerwaniu lub DMA. Podczas inicjalizacji ustawiam sygnał wyjściowy 1 Hz z ukłądu oraz, mimo że zegar domyślnie rusza po podłączeniu zasilania, zeruję bit STOP dla pewności.

void PCF8563_Init(I2C_HandleTypeDef *hi2c)
{
  hi2c_pcf8563 = hi2c;

  PCF8563_ClkoutFrequency(CLKOUT_FREQ_1HZ);
  PCF8563_STOPEnable(0);
}

Obsługa odbioru po DMA jest analogiczna do poprzednich przykładów. Cała obsługa zawarta jest w sekcji czwartej USER CODE.

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if(GPIO_Pin == PCF8563_INT_Pin)
  {
    PCF8563_ReceiveDateTimeDMA();
  }
}

void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
  PCF8563_CalculateDateTime(&r);
}

Prędkość działania PCF8563

Zerknijmy w przebiegi dla odczytu w blokującym przerwaniu oraz DMA.

100 kHz przerwanie

400 kHz przerwanie

100 kHz DMA

400 kHz DMA

Zestawię teraz te wyniki z tymi, które uzyskałem dla DS3231 oraz DS1307.

Zestawienie różnych RTC

Zebrałem wszystkie wyniki w tabeli.

DS3231DS1307PCF8563
100 kHz INT919 µs916 µs924 µs
400 kHz INT237 µsX308 µs
100 kHz DMA301µs301 µs302 µs
400 kHz DMA85 µsX107 µs

Jak możesz zauważyć wyniki między poszczególnymi układami są do siebie zbliżone. Zastanawia mnie czas 400 kHz DMA. Dlaczego widoczna jest różnica około 20 µs podczas zlecania transmisji DMA? Przerwanie SysTick ma ten sam priorytet, więc wykluczam zakłócenie przez niego. Być może analizator wprowadził jakiś błąd. Nie mniej jednak wyniki są porównywalne.

Podsumowanie

Sprawdziłem dwa inne popularne zegary RTC, które możesz wykorzystać w projektach – DS1307 oraz PCF8563. Obydwa w teorii nie grzeszą dokładnością, czego jeszcze nie badałem doświadczalnie. Być może niedługo taki test wykonam 🙂

Warto korzystać z szybszej transmisji I²C oraz z komunikacji przez DMA. Można zaoszczędzić na prawdę dużo potrzebnego czasu. Spotkałem się z małym zarzutem, że zawsze to jakieś DMA jest zajęte. Po to ono jest, aby z niego korzystać. Chyba że jest potrzebne do ważniejszych spraw. Wtedy można zrobić inny trick.

STM32 ma wbudowany układ RTC. Ma on co prawda beznadziejny oscylator RC z błędem na poziomie kilku %, ale może być taktowany zewnętrznym oscylatorem. Dzięki temu odciążysz DMA. To też jest warte sprawdzenia.

Pełny projekt wraz z biblioteką znajdziesz jak zwykle na moim GitHubie: DS1307, PCF8563

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.

5/5 - (3 votes)

Podobne artykuły

.

2 komentarze

Chemik · 18/09/2019 o 21:14

56kB RAM to na bogato ?

    Mateusz Salamon · 18/09/2019 o 21:24

    O fakt, pomyłka 😀

Dodaj komentarz

Avatar placeholder

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *