Почти у всех микроконтроллеров STM32 имеется модуль часов реального времени (RTC).
Далее только важные данные (базовая информация отсутствует).
Если запитать пин VBAT от батарейки 3V, то часы будут идти и при выключенном питании микроконтроллера.
Перед установкой батарейки, убедитесь, что на плате микроконтроллера присутствуют диоды и конденсатор в соответствующей цепи.
Точность хода часов зависит от качества кварцевого резонатора. Так как здесь нет компенсации по температуре, частота резонатора будет зависеть от его температуры.
Если часы спешат или отстают, значит частота резонатора не соответствует заявленной.
В таком случае можно выбрать другой источник тактирования для RTC.
Либо произвести подстройку имеющегося.
Как видно на скриншоте выше, параметр Asynchronous Predivider value здесь равен 32765. Часы тактируются кварцем, якобы на 32768 герц. Но данная частота в реальности может часто отличаться от экземпляра к экземпляру. По этой причине приходится выполнять калибровку увеличивая/уменьшая данный параметр для достижения приемлемой точности хода.
При замере частоты кварца на платах BluePill (F103xx) осциллографом с 10 мегаомным щупом резонанс кварца нарушался. Следовательно, произвести замер частоты столь маленького кварца довольно проблематично.
Также замечено, что при питании от «шумящего» USB тактирование RTC сильно замедлялось. Отсюда следует, что ход часов зависит и от качества питания.
После генерации проекта в CubeMX необходимо закомментировать процедуру установки даты и времени в функции static void MX_RTC_Init(void). Если этого не сделать, то при каждом перезапуске микроконтроллера будет происходить переустановка даты и времени.
ВАЖНО: На момент написания данного материала в модулях RTC некоторых семейств микроконтроллеров выявлена программная ошибка. Надеюсь, в будущем ее исправят. Проблема заключается в подвисании RTC примерно на 0,8 секунд при каждом перезапуске микроконтроллера в процедуре HAL_RTC_Init. То есть, если перезапустить контроллер 10 раз, то RTC в нем отстанет примерно на 8 секунд.
Для обхода данной проблемы было найдено следующее решение. В функции static void MX_RTC_Init(void). Нужно вот это дело:
1 2 3 4 | if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
} |
Взять в условие, предотвращающее повторную инициализацию модуля RTC (если он был ранее инициализирован), чтобы получилось так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0)
{
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
} else
{
HAL_PWR_EnableBkUpAccess();
__HAL_RCC_BKP_CLK_ENABLE();
__HAL_RCC_RTC_ENABLE();
HAL_NVIC_SetPriority(RTC_IRQn, 15, 0);
HAL_NVIC_EnableIRQ(RTC_IRQn);
} |
В целом, модуль RTC в микроконтроллерах STM32 довольно сносный. Главное, чтобы он был оригинальный и на плате стоял качественный кварцевый резонатор. После калибровки прескейлера резонатора удается укладываться в погрешность 1-2 секунды в сутки. Если требуется большая точность, необходимо использовать внешние модули RTC. Например, у модуля на микросхеме типа DS3231 погрешность заявлена до 0,5 секунд в сутки. Плюс в этой микросхеме имеется температурная компенсация.


