Może ktoś z was będzie miał jakiś pomysł, bo od paru dni nie mogę dojść do tego, co robię nie tak. Sytuacja wygląda następująco.
Środowisko: Płytka NUCLEO-L031K6, programowana za pomocą IDE AtollicSTUDIO. Projekt generowany narzędziem STM32CubeMX.
Software: Biblioteka do obsługi DCF77, przeportowana z Arduino. Do tego biblioteka sterująca wyświetlaczem od Nokii, przeportowana z AVR. Obydwie zdają się działać prawidłowo.
DCF odczytuje w przerwaniu impulsy z modułu i sprawdza poprawność ramek. Kontrolowane jest m.in. to, czy odebrany czas nie różni się za bardzo od systemowego zegara. Jeśli mamy do czynienia z taką sytuacją, konieczne jest odebranie dwóch prawidłowych ramek, jedna po drugiej. Oryginał korzystał w tym celu z jakiejś arduinowej biblioteki, ja przerobiłem to na standardowe time.h, podkładając wszędzie gdzie trzeba wywołania time(NULL).
Oczywiście zdefiniowałem w kodzie swoją własną funkcję time(), która czyta systemowy RTC, wypełnia pobranymi wartościami strukturę struct tm, a następnie przy pomocy mktime() generuje timestamt time_t.
Sam moduł RTC jest obsługiwany za pomocą bibliotek HAL. Po odebraniu nowej ramki zegar jest ustawiany wartościami uzyskanymi za pośrednictwem gmtime().
I teraz przechodząc do sedna sprawy: na początku wszystko zdaje się działać prawidłowo. Po starcie układu zegar zaczyna odliczać w górę, a jego aktualną wartość wyświetla się na LCD. Jeśli pojawią się odpowiednie warunki propagacyjne, DCF zaczyna dobierać ramki i przestawia zegar. Dodatkowo na LCD wyrzucam też info o czasie ostatniej poprawnej synchronizacji. Potrafi to działać prawidłowo przez kilka godzin, aż w końcu coś się wysypuje. Na przykład wczoraj około 20.00 UTC zegar stwierdził, że jest 4.00 UTC następnego dnia. Żeby było ciekawiej, kolejne ramki DCF były nadal odbierane, a na ekranie pojawiała się informacja o udanych synchronizacjach, oznaczonych prawidłowym czasem (!).
Kilka rzeczy nie daje mi spokoju:
- Dokładność tej anomalii - obserwowałem ją kilka razy i OIDP zawsze było to osiem godzin do przodu. Nie chodzi więc o odebranie jakimś cudem błędnej ramki.
- Przygotowana przeze mnie funkcje time() najwyraźniej zwraca cały czas prawidłowego timestampa, bo inaczej kolejne synchronizacje nie dochodziłyby do skutku. Program stwierdziłby rozjechanie się RTC z odbieranym czasem, czekając na dwie poprawne ramki. Wtedy ustawiłby zegar i wszystko wróciłoby do normy. Tak się jednak nie dzieje. Po pojawieniu się anomalia pozostaje na stałe.
W chwili obecnej do pobierania czasu z RTC używam kombinacji time() i gmtime(), a uzyskane wartości ze struktury wyrzucam na ekran. Po udanej synchronizacji odebrany czas z DCF jest zapisywany do zmiennej i również trafia na ekran za pośrednictwem gmtime().
Ktoś ma jakiś pomysł, co mogę robić nie tak? Może time.h w przypadku mikrokontrolerów wymaga jakiegoś przygotowania (poza podstawieniem własnej funkcji time())? W jaki sposób chociażby definiuje się w niej strefę czasową. Pod Linuksem ustawiało się zmienna środowiskową. A na małym mikrokontrolerze?